Explorar o código

知识库,积分导出功能调整

徐滕 hai 2 semanas
pai
achega
1d9836763c

+ 14 - 0
src/main/java/com/jeeplus/modules/WorkKnowledgeBase/dao/WorkKnowledgeBasePointDetailDao.java

@@ -210,4 +210,18 @@ public interface WorkKnowledgeBasePointDetailDao extends CrudDao<WorkKnowledgeBa
      * 钻取查询总数
      */
     int findDrillDownCount(UserPointDetail userPointDetail);
+
+    /**
+     * 查询指定时间之后的兑换扣减记录(按创建时间倒序)
+     * @param since 起始时间
+     * @return 兑换扣减记录列表
+     */
+    List<WorkKnowledgeBasePointDetail> findExchangeRecordsAfter(@Param("since") java.util.Date since);
+
+    /**
+     * 统计用户当前有效的基础积分兑换扣减记录数(用于取消兑换后判断是否需要恢复首次兑换标记)
+     * @param userId 用户ID
+     * @return 记录数
+     */
+    int countUserBasicExchangeRecords(@Param("userId") String userId);
 }

+ 229 - 0
src/main/java/com/jeeplus/modules/WorkKnowledgeBase/service/WorkKnowledgeBasePointExchangeService.java

@@ -395,6 +395,231 @@ public class WorkKnowledgeBasePointExchangeService extends CrudService<WorkKnowl
     }
 
     /**
+     * 批量兑换并获取整合导出数据(基础积分+贡献积分同时兑换)
+     * 导出表格包含两类积分的兑换情况,兑换金额为两类合计
+     * 管理员不参与兑换,不导出;按部门排序,部门内按兑换金额倒序
+     * @return 整合导出用的用户积分数据列表
+     */
+    @Transactional(readOnly = false)
+    public List<WorkKnowledgeBasePoint> batchExchangeBothForExport() {
+        // 1. 获取两类积分的用户ID并集
+        java.util.Set<String> userIdSet = new java.util.LinkedHashSet<>();
+        List<String> basicUserIds = pointDetailDao.findUserIdsByColumnId("1");
+        List<String> contribUserIds = pointDetailDao.findUserIdsByColumnId("2");
+        if (basicUserIds != null) userIdSet.addAll(basicUserIds);
+        if (contribUserIds != null) userIdSet.addAll(contribUserIds);
+
+        if (userIdSet.isEmpty()) {
+            return new java.util.ArrayList<>();
+        }
+
+        // 2. 先查询所有用户积分汇总(用于获取姓名、部门等信息,以及过滤管理员)
+        List<WorkKnowledgeBasePoint> allUsers = pointDetailDao.findAllUserPointSummary();
+        Map<String, WorkKnowledgeBasePoint> userMap = new HashMap<>();
+        for (WorkKnowledgeBasePoint u : allUsers) {
+            userMap.put(u.getUserId(), u);
+        }
+
+        // 3. 读取兑换规则
+        Integer firstThreshold = getRuleValueByType("91");
+        Integer nonFirstThreshold = getRuleValueByType("92");
+        Integer stepValue = getRuleValueByType("93");
+        if (firstThreshold == null) firstThreshold = 300;
+        if (nonFirstThreshold == null) nonFirstThreshold = 100;
+        if (stepValue == null) stepValue = 100;
+
+        // 记录每个用户的兑换量和原始积分
+        Map<String, Integer> exchangedBasicMap = new HashMap<>();
+        Map<String, Integer> exchangedContribMap = new HashMap<>();
+        Map<String, Integer> originalBasicMap = new HashMap<>();
+        Map<String, Integer> originalContribMap = new HashMap<>();
+        Map<String, Boolean> isFirstExchangeMap = new HashMap<>();
+        // 记录参与兑换的用户ID
+        java.util.Set<String> exchangedUserIds = new java.util.HashSet<>();
+
+        // 4. 逐用户同时执行基础积分和贡献积分兑换
+        for (String userId : userIdSet) {
+            try {
+                // 管理员不参与兑换,直接跳过
+                WorkKnowledgeBasePoint userInfo = userMap.get(userId);
+                if (userInfo != null && "管理员".equals(userInfo.getUserName())) {
+                    continue;
+                }
+
+                // === 基础积分兑换 ===
+                int basicPoints = pointDetailDao.sumUserPointByColumnId(userId, "1");
+                originalBasicMap.put(userId, basicPoints);
+
+                WorkKnowledgeBaseUserExchangeFlag flag = exchangeFlagDao.getByUserId(userId);
+                if (flag == null) {
+                    flag = new WorkKnowledgeBaseUserExchangeFlag();
+                    flag.setId(com.jeeplus.common.utils.IdGen.uuid());
+                    flag.setUserId(userId);
+                    flag.setIsFirstExchanged(0);
+                    flag.setDelFlag("0");
+                    flag.preInsert();
+                    exchangeFlagDao.insert(flag);
+                }
+                boolean isFirstExchange = (flag.getIsFirstExchanged() == 0 || flag.getIsFirstExchanged() == null);
+                isFirstExchangeMap.put(userId, isFirstExchange);
+                int threshold = isFirstExchange ? firstThreshold : nonFirstThreshold;
+                int basicExchanged = 0;
+                if (basicPoints >= threshold) {
+                    basicExchanged = (basicPoints / stepValue) * stepValue;
+                    if (basicExchanged > 0) {
+                        WorkKnowledgeBasePointDetail detail = new WorkKnowledgeBasePointDetail();
+                        detail.setId(com.jeeplus.common.utils.IdGen.uuid());
+                        detail.setUserId(userId);
+                        detail.setChangeType(9);
+                        detail.setCategoryId("1"); // 基础积分分类,使扣减自然计入基础积分汇总
+                        detail.setPoint(-basicExchanged);
+                        detail.setIsManualScore("0");
+                        detail.setDelFlag("0");
+                        detail.preInsert();
+                        pointDetailDao.insert(detail);
+                        if (isFirstExchange) {
+                            exchangeFlagDao.updateFirstExchangeStatus(userId, 1);
+                        }
+                        exchangedUserIds.add(userId);
+                    }
+                }
+                exchangedBasicMap.put(userId, basicExchanged);
+
+                // === 贡献积分兑换(全额清零) ===
+                int contributionPoints = pointDetailDao.sumUserPointByColumnId(userId, "2");
+                originalContribMap.put(userId, contributionPoints);
+
+                int contribExchanged = 0;
+                if (contributionPoints > 0) {
+                    contribExchanged = contributionPoints;
+                    WorkKnowledgeBasePointDetail cpDetail = new WorkKnowledgeBasePointDetail();
+                    cpDetail.setId(com.jeeplus.common.utils.IdGen.uuid());
+                    cpDetail.setUserId(userId);
+                    cpDetail.setChangeType(9);
+                    cpDetail.setCategoryId("2"); // 贡献积分分类,使扣减自然计入贡献积分汇总
+                    cpDetail.setPoint(-contribExchanged);
+                    cpDetail.setIsManualScore("0");
+                    cpDetail.setDelFlag("0");
+                    cpDetail.preInsert();
+                    pointDetailDao.insert(cpDetail);
+                    exchangedUserIds.add(userId);
+                }
+                exchangedContribMap.put(userId, contribExchanged);
+            } catch (Exception e) {
+                // 单个用户失败不影响其他用户,继续处理
+                continue;
+            }
+        }
+
+        // 5. 组装导出数据(只保留实际参与兑换的用户,剩余=兑换前-兑换量)
+        List<WorkKnowledgeBasePoint> exportList = new java.util.ArrayList<>();
+        for (WorkKnowledgeBasePoint item : allUsers) {
+            if (!exchangedUserIds.contains(item.getUserId())) {
+                continue;
+            }
+            // 管理员不导出
+            if ("管理员".equals(item.getUserName())) {
+                continue;
+            }
+
+            int exBasic = exchangedBasicMap.containsKey(item.getUserId()) ? exchangedBasicMap.get(item.getUserId()) : 0;
+            int exContrib = exchangedContribMap.containsKey(item.getUserId()) ? exchangedContribMap.get(item.getUserId()) : 0;
+            int origBasic = originalBasicMap.containsKey(item.getUserId()) ? originalBasicMap.get(item.getUserId()) : 0;
+            int origContrib = originalContribMap.containsKey(item.getUserId()) ? originalContribMap.get(item.getUserId()) : 0;
+
+            item.setExchangedBasicPoint(exBasic);
+            item.setExchangedContributionPoint(exContrib);
+            item.setRemainingBasicPoint(origBasic - exBasic);
+            item.setRemainingContributionPoint(origContrib - exContrib);
+            item.setOriginalBasicPoint(origBasic);
+            item.setOriginalContributionPoint(origContrib);
+
+            // 兑换金额 = 基础积分兑换金额 + 贡献积分兑换金额
+            boolean isFirst = isFirstExchangeMap.containsKey(item.getUserId()) ? isFirstExchangeMap.get(item.getUserId()) : false;
+            int basicAmt = calculateExchangeAmount("basic", exBasic, isFirst);
+            int contribAmt = calculateExchangeAmount("contribution", exContrib, false);
+            item.setExchangeAmount(basicAmt + contribAmt);
+
+            exportList.add(item);
+        }
+
+        // 6. 排序:先按部门排序,部门内按兑换金额倒序
+        exportList.sort((a, b) -> {
+            String deptA = a.getOfficeName() != null ? a.getOfficeName() : "";
+            String deptB = b.getOfficeName() != null ? b.getOfficeName() : "";
+            int deptCmp = deptA.compareTo(deptB);
+            if (deptCmp != 0) {
+                return deptCmp;
+            }
+            int amtA = a.getExchangeAmount() != null ? a.getExchangeAmount() : 0;
+            int amtB = b.getExchangeAmount() != null ? b.getExchangeAmount() : 0;
+            return Integer.compare(amtB, amtA);
+        });
+
+        return exportList;
+    }
+
+    /**
+     * 取消上次兑换(用于导出文档出错时的回退)
+     * 不依赖remarks,兼容历史兑换记录:一次兑换在同一请求内连续插入,create_date非常接近;
+     * 从最新一条兑换记录往前收集,相邻两条时间间隔超过阈值即视为上一批次,停止收集。
+     * 收集到的记录物理删除(与取消点赞删除积分记录的处理方式一致),删除后积分自动恢复;
+     * 若某用户的基础积分兑换记录被全部删除,说明被取消的即是其首次兑换,重置首次兑换标记。
+     * @return 操作结果信息
+     */
+    @Transactional(readOnly = false)
+    public String cancelLastExchange() {
+        // 1. 查询最近7天内的兑换扣减记录(按创建时间倒序)
+        Date since = new Date(System.currentTimeMillis() - 7L * 24 * 60 * 60 * 1000);
+        List<WorkKnowledgeBasePointDetail> recentRecords = pointDetailDao.findExchangeRecordsAfter(since);
+        if (recentRecords == null || recentRecords.isEmpty()) {
+            return "未找到可取消的兑换记录";
+        }
+
+        // 2. 从最新记录开始聚类:相邻两条间隔超过10分钟即视为不同批次
+        final long BATCH_GAP_MILLIS = 10L * 60 * 1000;
+        List<WorkKnowledgeBasePointDetail> lastBatch = new java.util.ArrayList<>();
+        Date prevDate = null;
+        for (WorkKnowledgeBasePointDetail record : recentRecords) {
+            if (record.getCreateDate() == null) {
+                continue;
+            }
+            if (prevDate != null && (prevDate.getTime() - record.getCreateDate().getTime()) > BATCH_GAP_MILLIS) {
+                break;
+            }
+            lastBatch.add(record);
+            prevDate = record.getCreateDate();
+        }
+        if (lastBatch.isEmpty()) {
+            return "未找到可取消的兑换记录";
+        }
+
+        // 3. 删除该批次记录,并收集涉及基础积分兑换的用户
+        java.util.Set<String> basicExchangeUserIds = new java.util.HashSet<>();
+        for (WorkKnowledgeBasePointDetail record : lastBatch) {
+            if ("1".equals(record.getCategoryId())) {
+                basicExchangeUserIds.add(record.getUserId());
+            }
+            pointDetailDao.delete(record);
+        }
+
+        // 4. 恢复首次兑换标记:用户已无其他基础兑换记录,说明被取消的即是首次兑换
+        int restoredCount = 0;
+        for (String userId : basicExchangeUserIds) {
+            int remainCount = pointDetailDao.countUserBasicExchangeRecords(userId);
+            if (remainCount == 0) {
+                WorkKnowledgeBaseUserExchangeFlag flag = exchangeFlagDao.getByUserId(userId);
+                if (flag != null && flag.getIsFirstExchanged() != null && flag.getIsFirstExchanged() == 1) {
+                    exchangeFlagDao.updateFirstExchangeStatus(userId, 0);
+                    restoredCount++;
+                }
+            }
+        }
+
+        return "已取消上次兑换,共删除" + lastBatch.size() + "条兑换记录";
+    }
+
+    /**
      * 预览兑换明细(只读,不写DB)
      * 计算每个用户的兑换情况:当前积分、预计兑换量、兑换后剩余
      * @param exchangeType 兑换类型:basic-基础积分, contribution-贡献积分
@@ -470,6 +695,10 @@ public class WorkKnowledgeBasePointExchangeService extends CrudService<WorkKnowl
             if (!previewUserIds.contains(item.getUserId())) {
                 continue;
             }
+            // 管理员不可兑换,不展示
+            if ("管理员".equals(item.getUserName())) {
+                continue;
+            }
 
             int exBasic = previewExchangedBasicMap.containsKey(item.getUserId()) ? previewExchangedBasicMap.get(item.getUserId()) : 0;
             int exContrib = previewExchangedContribMap.containsKey(item.getUserId()) ? previewExchangedContribMap.get(item.getUserId()) : 0;

+ 45 - 36
src/main/java/com/jeeplus/modules/WorkKnowledgeBase/web/WorkKnowledgeBasePointController.java

@@ -259,62 +259,50 @@ public class WorkKnowledgeBasePointController extends BaseController {
     public String exportExchange(@RequestParam(required = false) String exchangeType,
                                  HttpServletResponse response, RedirectAttributes redirectAttributes) {
         try {
-            // 默认兑换基础积分
+            // 默认兑换基础积分(参数保留兼容,导出为两类积分整合表格)
             if (StringUtils.isBlank(exchangeType)) {
                 exchangeType = "basic";
             }
-
-            System.out.println("========== 开始导出积分兑换,类型:" + exchangeType + " ==========");
-
-            // 执行批量兑换并获取导出数据
-            List<WorkKnowledgeBasePoint> exportList = pointExchangeService.batchExchangeForExport(exchangeType);
+        
+            System.out.println("========== 开始导出积分兑换(基础+贡献整合)==========");
+        
+            // 执行批量兑换(基础+贡献同时)并获取整合导出数据
+            List<WorkKnowledgeBasePoint> exportList = pointExchangeService.batchExchangeBothForExport();
             System.out.println("========== 导出数据条数:" + (exportList != null ? exportList.size() : 0) + " ==========");
-
-            // 根据兑换类型动态生成Excel列
+        
+            // 整合表格固定10列:姓名、所属部门、手机号、贡献积分可兑换、贡献积分兑换、贡献兑换后剩余、基础积分可兑换、基础积分兑换、基础兑换后剩余、兑换金额(元)
             String fileName = "积分兑换人员信息" + DateUtils.getDate("yyyyMMddHHmmss") + ".xlsx";
-            String[] headers;
-            if ("basic".equals(exchangeType)) {
-                // 基础积分兑换:姓名、所属部门、手机号、可兑换积分、基础积分兑换、兑换后剩余积分、兑换金额
-                headers = new String[]{"姓名", "所属部门", "手机号", "可兑换积分", "基础积分兑换", "兑换后剩余积分", "兑换金额(元)"};
-            } else {
-                // 贡献积分兑换:姓名、所属部门、手机号、可兑换积分、贡献积分兑换、兑换后剩余积分、兑换金额
-                headers = new String[]{"姓名", "所属部门", "手机号", "可兑换积分", "贡献积分兑换", "兑换后剩余积分", "兑换金额(元)"};
-            }
+            String[] headers = new String[]{"姓名", "所属部门", "手机号", "贡献积分可兑换积分", "贡献积分兑换", "贡献积分兑换后剩余积分", "基础积分可兑换积分", "基础积分兑换", "基础积分兑换后剩余积分", "兑换金额(元)"};
             ExportExcel exportExcel = new ExportExcel("积分兑换人员信息", headers);
-
+        
             for (WorkKnowledgeBasePoint item : exportList) {
                 int exBasic = item.getExchangedBasicPoint() != null ? item.getExchangedBasicPoint() : 0;
                 int exContrib = item.getExchangedContributionPoint() != null ? item.getExchangedContributionPoint() : 0;
                 // 可兑换积分(兑换前的原始积分)
                 int origBasic = item.getOriginalBasicPoint() != null ? item.getOriginalBasicPoint() : 0;
                 int origContrib = item.getOriginalContributionPoint() != null ? item.getOriginalContributionPoint() : 0;
-                // 兑换后剩余积分(已从DB直接获取,因为兑换记录category_id已正确归类)
+                // 兑换后剩余积分
                 int remainBasic = item.getRemainingBasicPoint() != null ? item.getRemainingBasicPoint() : 0;
                 int remainContrib = item.getRemainingContributionPoint() != null ? item.getRemainingContributionPoint() : 0;
-
+                // 兑换金额(两类合计)
+                int exchangeAmt = item.getExchangeAmount() != null ? item.getExchangeAmount() : 0;
+        
                 org.apache.poi.ss.usermodel.Row row = exportExcel.addRow();
                 int col = 0;
                 // 公共列:姓名、所属部门、手机号
                 exportExcel.addCell(row, col++, item.getUserName(), 2, String.class);
                 exportExcel.addCell(row, col++, item.getOfficeName(), 2, String.class);
                 exportExcel.addCell(row, col++, item.getMobile() != null ? item.getMobile() : (item.getPhone() != null ? item.getPhone() : ""), 2, String.class);
-
-                // 根据兑换类型添加对应列
-                if ("basic".equals(exchangeType)) {
-                    // 基础积分兑换:显示可兑换积分、基础积分兑换量、兑换后剩余积分、兑换金额
-                    exportExcel.addCell(row, col++, origBasic, 2, Integer.class);
-                    exportExcel.addCell(row, col++, exBasic, 2, Integer.class);
-                    exportExcel.addCell(row, col++, remainBasic, 2, Integer.class);
-                    int exchangeAmt = item.getExchangeAmount() != null ? item.getExchangeAmount() : 0;
-                    exportExcel.addCell(row, col++, exchangeAmt, 2, Integer.class);
-                } else {
-                    // 贡献积分兑换:显示可兑换积分、贡献积分兑换量、兑换后剩余积分、兑换金额
-                    exportExcel.addCell(row, col++, origContrib, 2, Integer.class);
-                    exportExcel.addCell(row, col++, exContrib, 2, Integer.class);
-                    exportExcel.addCell(row, col++, remainContrib, 2, Integer.class);
-                    int exchangeAmt = item.getExchangeAmount() != null ? item.getExchangeAmount() : 0;
-                    exportExcel.addCell(row, col++, exchangeAmt, 2, Integer.class);
-                }
+                // 贡献积分三列
+                exportExcel.addCell(row, col++, origContrib, 2, Integer.class);
+                exportExcel.addCell(row, col++, exContrib, 2, Integer.class);
+                exportExcel.addCell(row, col++, remainContrib, 2, Integer.class);
+                // 基础积分三列
+                exportExcel.addCell(row, col++, origBasic, 2, Integer.class);
+                exportExcel.addCell(row, col++, exBasic, 2, Integer.class);
+                exportExcel.addCell(row, col++, remainBasic, 2, Integer.class);
+                // 兑换金额(元):最后一列
+                exportExcel.addCell(row, col++, exchangeAmt, 2, Integer.class);
             }
 
             exportExcel.write(response, fileName).dispose();
@@ -326,6 +314,27 @@ public class WorkKnowledgeBasePointController extends BaseController {
     }
 
     /**
+     * 取消上次兑换(导出文档出错时的回退操作)
+     * 将最近一次兑换批次的扣减记录逻辑删除,并恢复首次兑换标记
+     * 独立权限控制:仅授权用户可见可操作
+     */
+    @RequiresPermissions("workKnowledgeBase:point:cancelExchange")
+    @RequestMapping(value = "cancelLastExchange")
+    @ResponseBody
+    public Map<String, Object> cancelLastExchange() {
+        Map<String, Object> result = new HashMap<>();
+        try {
+            String message = pointExchangeService.cancelLastExchange();
+            result.put("success", true);
+            result.put("message", message);
+        } catch (Exception e) {
+            result.put("success", false);
+            result.put("message", "取消上次兑换失败:" + e.getMessage());
+        }
+        return result;
+    }
+
+    /**
      * 积分统计三层表头导出:公司级、部门级、员工级
      * L1: parent_id=0的分类 → L2: 子分类 → L3: 规则point_name
      * 每个L1组包含: L2子分类(L3规则列) + 兑现列 + 小计列

+ 21 - 1
src/main/resources/mappings/modules/WorkKnowledgeBase/WorkKnowledgeBasePointDetailDao.xml

@@ -125,7 +125,7 @@
             u.phone     AS "phone",
             o.name      AS "officeName",
             COALESCE(SUM(d.point), 0) AS "totalPoint",
-            COALESCE(SUM(CASE WHEN DATE_FORMAT(d.create_date, '%Y-%m') = DATE_FORMAT(CURDATE(), '%Y-%m') THEN d.point ELSE 0 END), 0) AS "monthlyPoint"
+            COALESCE(SUM(CASE WHEN DATE_FORMAT(d.create_date, '%Y-%m') = DATE_FORMAT(CURDATE(), '%Y-%m') AND IFNULL(d.change_type, 0) != 9 THEN d.point ELSE 0 END), 0) AS "monthlyPoint"
         FROM sys_user u
         LEFT JOIN work_knowledge_base_point_detail d ON d.user_id = u.id AND d.del_flag = '0'
         LEFT JOIN work_knowledge_point_category cat ON cat.id = d.category_id AND cat.del_flag = '0'
@@ -906,4 +906,24 @@
         </where>
     </select>
 
+    <!-- 查询指定时间之后的兑换扣减记录(按创建时间倒序,用于取消上次兑换时按时间聚类定位批次) -->
+    <select id="findExchangeRecordsAfter" resultType="com.jeeplus.modules.WorkKnowledgeBase.entity.WorkKnowledgeBasePointDetail">
+        SELECT <include refid="pointDetailColumns"/>
+        FROM work_knowledge_base_point_detail a
+        WHERE a.del_flag = '0'
+          AND a.change_type = 9
+          AND a.create_date &gt;= #{since}
+        ORDER BY a.create_date DESC
+    </select>
+
+    <!-- 统计用户当前有效的基础积分兑换扣减记录数 -->
+    <select id="countUserBasicExchangeRecords" resultType="int">
+        SELECT COUNT(*)
+        FROM work_knowledge_base_point_detail
+        WHERE del_flag = '0'
+          AND change_type = 9
+          AND category_id = '1'
+          AND user_id = #{userId}
+    </select>
+
 </mapper>

+ 31 - 0
src/main/webapp/webpage/modules/WorkKnowledgeBase/workKnowledgeBasePointList.jsp

@@ -187,6 +187,9 @@
 						<shiro:hasPermission name="workKnowledgeBase:point:listAll">
 							<button type="button" data-toggle="tooltip" data-placement="top" class="layui-btn layui-btn-sm layui-bg-blue" id="exportPointUser"> 下载积分兑换人员信息</button>
 						</shiro:hasPermission>
+						<shiro:hasPermission name="workKnowledgeBase:point:cancelExchange">
+							<button type="button" data-toggle="tooltip" data-placement="top" class="layui-btn layui-btn-sm layui-btn-danger" id="cancelLastExchangeBtn" title="导出文档出现问题时,可撤销最近一次兑换"> 取消上次兑换</button>
+						</shiro:hasPermission>
 					</div>
 					<div style="float: right;margin-right: 30px;">
 						<label class="layui-form-label double-line">排序规则:</label>
@@ -325,6 +328,34 @@
             
         return false;
     });
+
+    // 取消上次兑换(导出文档出现问题时的回退操作)
+    $('#cancelLastExchangeBtn').click(function(){
+        top.layer.confirm('确定取消上次兑换吗?<br><span style="color:#999;">将删除最近一次兑换的扣减记录并恢复积分,仅在导出文档出现问题时使用。</span>', {icon: 3, title: '取消上次兑换'}, function(confirmIndex){
+            top.layer.close(confirmIndex);
+            var loadIdx = top.layer.load(2, {shade: [0.3, '#fff']});
+            $.ajax({
+                url: '${ctx}/workKnowledgeBase/point/cancelLastExchange',
+                type: 'POST',
+                dataType: 'json',
+                success: function(res){
+                    top.layer.close(loadIdx);
+                    if (res && res.success) {
+                        top.layer.msg(res.message || '取消成功', {icon: 1, time: 2000});
+                        // 刷新列表
+                        search();
+                    } else {
+                        top.layer.msg((res && res.message) || '取消失败', {icon: 2, time: 3000});
+                    }
+                },
+                error: function(){
+                    top.layer.close(loadIdx);
+                    top.layer.msg('请求失败,请重试', {icon: 2});
+                }
+            });
+        });
+        return false;
+    });
 </script>
 </body>
 </html>