Prechádzať zdrojové kódy

知识库,阅读调整:审核通过的知识库查看才给积分

徐滕 3 týždňov pred
rodič
commit
b3dad928f8

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

@@ -378,6 +378,101 @@ public class WorkKnowledgeBasePointExchangeService extends CrudService<WorkKnowl
     }
 
     /**
+     * 预览兑换明细(只读,不写DB)
+     * 计算每个用户的兑换情况:当前积分、预计兑换量、兑换后剩余
+     * @param exchangeType 兑换类型:basic-基础积分, contribution-贡献积分
+     * @return 预览用的用户积分数据列表(只包含满足兑换条件的用户)
+     */
+    public List<WorkKnowledgeBasePoint> previewExchange(String exchangeType) {
+        // 1. 根据兑换类型获取有对应积分的用户ID列表
+        String columnId = "basic".equals(exchangeType) ? "1" : "2";
+        List<String> userIdList = pointDetailDao.findUserIdsByColumnId(columnId);
+
+        if (userIdList == null || userIdList.isEmpty()) {
+            return new java.util.ArrayList<>();
+        }
+
+        // 2. 读取兑换规则
+        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;
+
+        // 记录参与预览的用户ID
+        java.util.Set<String> previewUserIds = new java.util.HashSet<>();
+        Map<String, Integer> previewExchangedBasicMap = new HashMap<>();
+        Map<String, Integer> previewExchangedContribMap = new HashMap<>();
+        Map<String, Integer> previewOriginalBasicMap = new HashMap<>();
+        Map<String, Integer> previewOriginalContribMap = new HashMap<>();
+
+        // 3. 逐用户计算兑换情况(不写DB)
+        for (String userId : userIdList) {
+            try {
+                if ("basic".equals(exchangeType)) {
+                    int basicPoints = pointDetailDao.sumUserPointByColumnId(userId, "1");
+                    previewOriginalBasicMap.put(userId, basicPoints);
+
+                    WorkKnowledgeBaseUserExchangeFlag flag = exchangeFlagDao.getByUserId(userId);
+                    boolean isFirstExchange = (flag == null || flag.getIsFirstExchanged() == 0 || flag.getIsFirstExchanged() == null);
+                    int threshold = isFirstExchange ? firstThreshold : nonFirstThreshold;
+                    int basicExchanged = 0;
+                    if (basicPoints >= threshold) {
+                        basicExchanged = (basicPoints / stepValue) * stepValue;
+                        if (basicExchanged > 0) {
+                            previewUserIds.add(userId);
+                        }
+                    }
+                    previewExchangedBasicMap.put(userId, basicExchanged);
+                }
+
+                if ("contribution".equals(exchangeType)) {
+                    int contributionPoints = pointDetailDao.sumUserPointByColumnId(userId, "2");
+                    previewOriginalContribMap.put(userId, contributionPoints);
+
+                    if (contributionPoints > 0) {
+                        previewUserIds.add(userId);
+                        previewExchangedContribMap.put(userId, contributionPoints);
+                    }
+                }
+            } catch (Exception e) {
+                continue;
+            }
+        }
+
+        // 4. 查询所有用户的积分汇总
+        List<WorkKnowledgeBasePoint> allUsers = pointDetailDao.findAllUserPointSummary();
+
+        // 5. 过滤出满足兑换条件的用户,组装预览数据
+        List<WorkKnowledgeBasePoint> previewList = new java.util.ArrayList<>();
+        for (WorkKnowledgeBasePoint item : allUsers) {
+            if (!previewUserIds.contains(item.getUserId())) {
+                continue;
+            }
+
+            int exBasic = previewExchangedBasicMap.containsKey(item.getUserId()) ? previewExchangedBasicMap.get(item.getUserId()) : 0;
+            int exContrib = previewExchangedContribMap.containsKey(item.getUserId()) ? previewExchangedContribMap.get(item.getUserId()) : 0;
+            int currentBasic = item.getBasicPoint() != null ? item.getBasicPoint() : 0;
+            int currentContrib = item.getContributionPoint() != null ? item.getContributionPoint() : 0;
+            int origBasic = previewOriginalBasicMap.containsKey(item.getUserId()) ? previewOriginalBasicMap.get(item.getUserId()) : 0;
+            int origContrib = previewOriginalContribMap.containsKey(item.getUserId()) ? previewOriginalContribMap.get(item.getUserId()) : 0;
+
+            item.setExchangedBasicPoint(exBasic);
+            item.setExchangedContributionPoint(exContrib);
+            item.setOriginalBasicPoint(origBasic);
+            item.setOriginalContributionPoint(origContrib);
+            // 预览时的剩余 = 当前积分 - 预计兑换量
+            item.setRemainingBasicPoint(currentBasic - exBasic);
+            item.setRemainingContributionPoint(currentContrib - exContrib);
+
+            previewList.add(item);
+        }
+
+        return previewList;
+    }
+
+    /**
      * 根据rule_type获取规则配置的point_value值
      * @param ruleType 规则类型(91/92/93)
      * @return 规则值,如果不存在返回null

+ 47 - 0
src/main/java/com/jeeplus/modules/WorkKnowledgeBase/web/WorkKnowledgeBasePointController.java

@@ -28,6 +28,7 @@ import org.springframework.ui.Model;
 import org.springframework.web.bind.annotation.ModelAttribute;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.ResponseBody;
 import org.springframework.web.servlet.mvc.support.RedirectAttributes;
 
 import javax.servlet.http.HttpServletRequest;
@@ -180,6 +181,52 @@ public class WorkKnowledgeBasePointController extends BaseController {
     }
 
     /**
+     * 预览兑换明细(只读,不写DB,返回JSON)
+     * @param exchangeType 兑换类型:basic-基础积分, contribution-贡献积分
+     */
+    @RequiresPermissions("workKnowledgeBase:point:listAll")
+    @RequestMapping(value = "previewExchange")
+    @ResponseBody
+    public Map<String, Object> previewExchange(@RequestParam(required=false) String exchangeType) {
+        Map<String, Object> result = new HashMap<>();
+        try {
+            if (StringUtils.isBlank(exchangeType)) {
+                exchangeType = "basic";
+            }
+            List<WorkKnowledgeBasePoint> previewList = pointExchangeService.previewExchange(exchangeType);
+            result.put("success", true);
+            result.put("data", previewList);
+            result.put("exchangeType", exchangeType);
+            result.put("totalCount", previewList.size());
+        } catch (Exception e) {
+            result.put("success", false);
+            result.put("message", "预览兑换明细失败:" + e.getMessage());
+        }
+        return result;
+    }
+
+    /**
+     * 预览兑换明细页面(iframe弹窗用)
+     * @param exchangeType 兑换类型:basic-基础积分, contribution-贡献积分
+     */
+    @RequiresPermissions("workKnowledgeBase:point:listAll")
+    @RequestMapping(value = "previewExchangePage")
+    public String previewExchangePage(@RequestParam(required=false) String exchangeType, Model model) {
+        if (StringUtils.isBlank(exchangeType)) {
+            exchangeType = "basic";
+        }
+        try {
+            List<WorkKnowledgeBasePoint> previewList = pointExchangeService.previewExchange(exchangeType);
+            model.addAttribute("previewDataJson", new com.fasterxml.jackson.databind.ObjectMapper().writeValueAsString(previewList));
+        } catch (Exception e) {
+            model.addAttribute("previewDataJson", "[]");
+        }
+        model.addAttribute("exchangeType", exchangeType);
+        model.addAttribute("typeName", "basic".equals(exchangeType) ? "基础积分" : "贡献积分");
+        return "modules/WorkKnowledgeBase/workKnowledgeBasePointExchangePreview";
+    }
+
+    /**
      * 批量兑换积分并导出Excel
      * @param exchangeType 兑换类型:basic-基础积分, contribution-贡献积分
      */

+ 85 - 0
src/main/webapp/webpage/modules/WorkKnowledgeBase/workKnowledgeBasePointExchangePreview.jsp

@@ -0,0 +1,85 @@
+<%@ page contentType="text/html;charset=UTF-8" %>
+<%@ include file="/webpage/include/taglib.jsp"%>
+<html>
+<head>
+    <title>积分兑换预览</title>
+    <meta name="decorator" content="default"/>
+    <script src="${ctxStatic}/layer-v2.3/layui/layui.all.js" charset="utf-8"></script>
+    <style>
+        .preview-header { padding: 15px 15px 5px; }
+        .preview-header p { margin: 0 0 8px; font-size: 14px; color: #333; }
+        .preview-header .tip { color: #999; font-size: 12px; margin-top: 8px; }
+        .preview-table-wrap { padding: 0 15px 15px; }
+        /* 将分页器移到右侧 */
+        #previewTable + .layui-table-page {
+            text-align: right;
+        }
+    </style>
+</head>
+<body>
+<div class="preview-header">
+    <p>兑换类型:<b style="color:#1aa094;">${typeName}</b>,共 <b style="color:#FF5722;" id="totalCount">0</b> 人满足兑换条件</p>
+</div>
+<div class="preview-table-wrap">
+    <table class="layui-table" id="previewTable" lay-filter="previewTable"></table>
+</div>
+<p class="preview-header tip">* 确认后将执行扣分操作并下载Excel文件,请仔细核对</p>
+
+<script>
+    var exchangeType = '${exchangeType}';
+    var previewData = [];
+    try {
+        previewData = JSON.parse('${previewDataJson}'.replace(/&quot;/g, '"').replace(/&amp;/g, '&'));
+    } catch(e) {
+        previewData = [];
+    }
+
+    document.getElementById('totalCount').innerText = previewData.length;
+
+    // 添加序号
+    for (var i = 0; i < previewData.length; i++) {
+        previewData[i].idx = i + 1;
+    }
+
+    // 根据兑换类型动态设置列
+    var cols;
+    if (exchangeType === 'basic') {
+        cols = [[
+            {field:'idx', align:'center', title:'序号', width:55},
+            {field:'userName', align:'center', title:'姓名', minWidth:100},
+            {field:'officeName', align:'center', title:'所属部门', minWidth:140},
+            {field:'mobile', align:'center', title:'手机号', minWidth:120, templet:function(d){ return d.mobile || d.phone || ''; }},
+            {field:'originalBasicPoint', align:'center', title:'当前基础积分', width:120, templet:function(d){ return '<span style="color:#1aa094;font-weight:bold;">' + (d.originalBasicPoint || 0) + '</span>'; }},
+            {field:'exchangedBasicPoint', align:'center', title:'预计兑换', width:100, templet:function(d){ return '<span style="color:#FF5722;font-weight:bold;">' + (d.exchangedBasicPoint || 0) + '</span>'; }},
+            {field:'remainingBasicPoint', align:'center', title:'兑换后剩余', width:110}
+        ]];
+    } else {
+        cols = [[
+            {field:'idx', align:'center', title:'序号', width:55},
+            {field:'userName', align:'center', title:'姓名', minWidth:100},
+            {field:'officeName', align:'center', title:'所属部门', minWidth:140},
+            {field:'mobile', align:'center', title:'手机号', minWidth:120, templet:function(d){ return d.mobile || d.phone || ''; }},
+            {field:'originalContributionPoint', align:'center', title:'当前贡献积分', width:120, templet:function(d){ return '<span style="color:#1aa094;font-weight:bold;">' + (d.originalContributionPoint || 0) + '</span>'; }},
+            {field:'exchangedContributionPoint', align:'center', title:'预计兑换', width:100, templet:function(d){ return '<span style="color:#FF5722;font-weight:bold;">' + (d.exchangedContributionPoint || 0) + '</span>'; }},
+            {field:'remainingContributionPoint', align:'center', title:'兑换后剩余', width:110}
+        ]];
+    }
+
+    layui.use('table', function(){
+        layui.table.render({
+            elem: '#previewTable',
+            cols: cols,
+            data: previewData,
+            page: {
+                layout: ['count', 'prev', 'page', 'next', 'limit', 'skip'],
+                position: 'right'
+            },
+            limit: 10,
+            limits: [10, 15, 20, 30, 50],
+            skin: 'line',
+            size: 'sm'
+        });
+    });
+</script>
+</body>
+</html>

+ 68 - 48
src/main/webapp/webpage/modules/WorkKnowledgeBase/workKnowledgeBasePointList.jsp

@@ -228,60 +228,80 @@
         });
     });
 
-    // 下载积分兑换人员信息
-    var isExporting = false; // 防止重复导出标志
-    
+    // 下载积分兑换人员信息(两步交互:先预览确认,再执行兑换下载)
+    var isExporting = false;
+        
     $('#exportPointUser').click(function(){
-        // 防止重复点击和重复导出
         if (isExporting) {
-            console.log('正在导出中,请勿重复点击');
             return false;
         }
-        
-        var btn = $(this);
-        
-        // 从隐藏字段 columnId 获取当前选中的分类(1-基础积分,2-贡献积分)
+            
         var columnId = $('#columnId').val();
-        
-        isExporting = true;
-        btn.prop('disabled', true).text('兑换处理中,请稍候...');
-        
-        var randomId = "down_" + new Date().getTime();
-        var downForm = $('<form>', {
-            'action': '${ctx}/workKnowledgeBase/point/exportExchange',
-            'method': 'GET',
-            'style': 'display:none;'
-        }).appendTo('body');
-        
-        // 添加兑换类型参数:columnId=1 -> basic, columnId=2 -> contribution
-        $('<input>').attr({
-            type: 'hidden',
-            name: 'exchangeType',
-            value: columnId == '1' ? 'basic' : 'contribution'
-        }).appendTo(downForm);
-        
-        var downIframe = $('<iframe>', {'name':randomId,'style':'display:none;'}).appendTo('body');
-        downForm.attr('target', randomId);
-        
-        // 监听iframe加载完成,清理资源
-        downIframe.on('load', function(){
-            isExporting = false;
-            btn.prop('disabled', false).text(' 下载积分兑换人员信息');
-            downForm.remove();
-            downIframe.remove();
+        var exchangeType = columnId == '1' ? 'basic' : 'contribution';
+        var typeName = columnId == '1' ? '基础积分' : '贡献积分';
+            
+        // 第一步:打开预览弹窗(iframe方式,内嵌layui table分页)
+        top.layer.open({
+            type: 2,
+            area: ['85%', '80%'],
+            title: '积分兑换预览 - ' + typeName,
+            maxmin: true,
+            content: '${ctx}/workKnowledgeBase/point/previewExchangePage?exchangeType=' + exchangeType,
+            skin: 'three-btns',
+            btn: ['确认兑换并下载', '取消'],
+            btn1: function(index, layero) {
+                if (isExporting) {
+                    top.layer.msg('正在处理中,请稍候...', {icon: 0});
+                    return;
+                }
+                isExporting = true;
+                
+                // 显示加载提示
+                var loadingIndex = top.layer.load(2, {shade: [0.3, '#fff']});
+                    
+                // 第二步:确认兑换,提交表单下载
+                var iframeWin = layero.find('iframe')[0];
+                var randomId = "down_" + new Date().getTime();
+                var downForm = $('<form>', {
+                    'action': '${ctx}/workKnowledgeBase/point/exportExchange',
+                    'method': 'GET',
+                    'style': 'display:none;'
+                }).appendTo($(iframeWin.contentWindow.document.body));
+                    
+                $('<input>').attr({
+                    type: 'hidden',
+                    name: 'exchangeType',
+                    value: exchangeType
+                }).appendTo(downForm);
+                    
+                var downIframe = $('<iframe>', {'name': randomId, 'style': 'display:none;'}).appendTo(iframeWin.contentWindow.document.body);
+                downForm.attr('target', randomId);
+                    
+                downIframe.on('load', function() {
+                    isExporting = false;
+                    top.layer.close(loadingIndex);
+                    top.layer.close(index);
+                    try { downForm.remove(); downIframe.remove(); } catch(e) {}
+                    // 兑换完成后刷新列表
+                    search();
+                });
+                    
+                downForm.submit();
+                    
+                // 兗底:10秒后恢复
+                setTimeout(function() {
+                    isExporting = false;
+                    top.layer.close(loadingIndex);
+                    try { top.layer.close(index); } catch(e) {}
+                    try { downForm.remove(); downIframe.remove(); } catch(e) {}
+                    search();
+                }, 10000);
+            },
+            btn2: function(index) {
+                top.layer.close(index);
+            }
         });
-        
-        downForm.submit();
-        
-        // 兜底:5秒后恢复按钮状态并刷新列表
-        setTimeout(function(){
-            isExporting = false;
-            btn.prop('disabled', false).text(' 下载积分兑换人员信息');
-            try { downForm.remove(); downIframe.remove(); } catch(e){}
-            // 恢复按钮后刷新列表数据
-            search();
-        }, 5000);
-
+            
         return false;
     });
 </script>