Explorar el Código

积分调整,审核时必须阅读文件3分钟以上才可审核通过。点赞和阅读分数每条从1积分调整成0.5积分

徐滕 hace 3 semanas
padre
commit
b05adfe7da
Se han modificado 26 ficheros con 409 adiciones y 295 borrados
  1. 2 2
      src/main/java/com/jeeplus/modules/WorkKnowledgeBase/dao/WorkKnowledgeBasePointDetailDao.java
  2. 4 4
      src/main/java/com/jeeplus/modules/WorkKnowledgeBase/entity/UserPointDetail.java
  3. 3 3
      src/main/java/com/jeeplus/modules/WorkKnowledgeBase/entity/WkPointSnapshotDetail.java
  4. 21 21
      src/main/java/com/jeeplus/modules/WorkKnowledgeBase/entity/WkPointSnapshotSummary.java
  5. 18 18
      src/main/java/com/jeeplus/modules/WorkKnowledgeBase/entity/WorkKnowledgeBasePoint.java
  6. 4 4
      src/main/java/com/jeeplus/modules/WorkKnowledgeBase/entity/WorkKnowledgeBasePointDetail.java
  7. 2 2
      src/main/java/com/jeeplus/modules/WorkKnowledgeBase/entity/WorkKnowledgeBaseViolationRecord.java
  8. 60 53
      src/main/java/com/jeeplus/modules/WorkKnowledgeBase/service/WkPointSnapshotService.java
  9. 2 2
      src/main/java/com/jeeplus/modules/WorkKnowledgeBase/service/WorkKnowledgeBasePointDetailService.java
  10. 79 79
      src/main/java/com/jeeplus/modules/WorkKnowledgeBase/service/WorkKnowledgeBasePointExchangeService.java
  11. 3 3
      src/main/java/com/jeeplus/modules/WorkKnowledgeBase/service/WorkKnowledgeBaseReadLikeService.java
  12. 36 14
      src/main/java/com/jeeplus/modules/WorkKnowledgeBase/service/WorkKnowledgeBaseShareService.java
  13. 55 55
      src/main/java/com/jeeplus/modules/WorkKnowledgeBase/web/WorkKnowledgeBasePointController.java
  14. 4 4
      src/main/java/com/jeeplus/modules/WorkKnowledgeBase/web/WorkKnowledgeBaseShareController.java
  15. 1 1
      src/main/resources/mappings/modules/WorkKnowledgeBase/WkPointSnapshotDetailDao.xml
  16. 4 4
      src/main/resources/mappings/modules/WorkKnowledgeBase/WorkKnowledgeBasePointDetailDao.xml
  17. 2 2
      src/main/resources/mysqlDateBase/init_work_knowledge_base_point_rule_data.sql
  18. 66 0
      src/main/resources/mysqlDateBase/upgrade_read_like_half_point.sql
  19. 8 8
      src/main/resources/mysqlDateBase/wk_point_snapshot_tables.sql
  20. 1 1
      src/main/webapp/webpage/modules/WorkKnowledgeBase/workKnowledgeBasePointDrillDown.jsp
  21. 2 2
      src/main/webapp/webpage/modules/WorkKnowledgeBase/workKnowledgeBasePointExchangePreview.jsp
  22. 2 2
      src/main/webapp/webpage/modules/WorkKnowledgeBase/workKnowledgeBasePointList.jsp
  23. 5 5
      src/main/webapp/webpage/modules/WorkKnowledgeBase/workKnowledgeBasePointRanking.jsp
  24. 2 2
      src/main/webapp/webpage/modules/WorkKnowledgeBase/workKnowledgeBasePointUserDetail.jsp
  25. 1 1
      src/main/webapp/webpage/modules/WorkKnowledgeBase/workKnowledgeBasePointUserList.jsp
  26. 22 3
      src/main/webapp/webpage/modules/WorkKnowledgeBase/workKnowledgeBaseShareDetail.jsp

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

@@ -30,13 +30,13 @@ public interface WorkKnowledgeBasePointDetailDao extends CrudDao<WorkKnowledgeBa
     int findUserPointDetailCount(UserPointDetail userPointDetail);
 
     /** 根据用户ID和分类ID(含子节点)统计积分总和 */
-    int sumUserPointByColumnId(
+    double sumUserPointByColumnId(
         @Param("userId") String userId,
         @Param("columnId") String columnId
     );
 
     /** 根据用户ID、分类ID和积分类型统计积分总和 */
-    int sumUserPointByColumnIdWithPointType(
+    double sumUserPointByColumnIdWithPointType(
         @Param("userId") String userId,
         @Param("columnId") String columnId,
         @Param("pointType") String pointType

+ 4 - 4
src/main/java/com/jeeplus/modules/WorkKnowledgeBase/entity/UserPointDetail.java

@@ -24,8 +24,8 @@ public class UserPointDetail extends DataEntity<UserPointDetail> {
     /** 变动类型 1:创建加分 2:审核加分 */
     private Integer changeType;
 
-    /** 积分值 */
-    private Integer point;
+    /** 积分值(支持小数) */
+    private Double point;
 
     /** 分享名称 */
     private String shareName;
@@ -95,11 +95,11 @@ public class UserPointDetail extends DataEntity<UserPointDetail> {
         this.changeType = changeType;
     }
 
-    public Integer getPoint() {
+    public Double getPoint() {
         return point;
     }
 
-    public void setPoint(Integer point) {
+    public void setPoint(Double point) {
         this.point = point;
     }
 

+ 3 - 3
src/main/java/com/jeeplus/modules/WorkKnowledgeBase/entity/WkPointSnapshotDetail.java

@@ -28,7 +28,7 @@ public class WkPointSnapshotDetail extends DataEntity<WkPointSnapshotDetail> {
     private String categoryName;        // 分类名称
     private String ruleId;              // 规则ID
     private Integer ruleType;           // 规则类型(1=创建,2=审核,10=阅读,20=点赞)
-    private Integer point;              // 积分值
+    private Double point;              // 积分值
     private Date pointCreateDate;       // 积分产生时间
 
     // 查询条件(非持久化)
@@ -89,8 +89,8 @@ public class WkPointSnapshotDetail extends DataEntity<WkPointSnapshotDetail> {
     public Integer getRuleType() { return ruleType; }
     public void setRuleType(Integer ruleType) { this.ruleType = ruleType; }
 
-    public Integer getPoint() { return point; }
-    public void setPoint(Integer point) { this.point = point; }
+    public Double getPoint() { return point; }
+    public void setPoint(Double point) { this.point = point; }
 
     public Date getPointCreateDate() { return pointCreateDate; }
     public void setPointCreateDate(Date pointCreateDate) { this.pointCreateDate = pointCreateDate; }

+ 21 - 21
src/main/java/com/jeeplus/modules/WorkKnowledgeBase/entity/WkPointSnapshotSummary.java

@@ -22,13 +22,13 @@ public class WkPointSnapshotSummary extends DataEntity<WkPointSnapshotSummary> {
     private String userId;              // 用户ID(员工级才有)
     private String userName;            // 用户姓名
     private Integer uploadCount;        // 上传文档数
-    private Integer basicSubtotal;      // 基础积分汇总
-    private Integer basicExchange;      // 基础已兑换积分
-    private Integer basicRemaining;     // 基础剩余积分
-    private Integer contribSubtotal;    // 贡献积分汇总(含扣除)
-    private Integer contribDeduction;   // 贡献-扣除积分
-    private Integer contribExchange;    // 贡献已兑换积分
-    private Integer contribRemaining;   // 贡献剩余积分
+    private Double basicSubtotal;      // 基础积分汇总
+    private Double basicExchange;      // 基础已兑换积分
+    private Double basicRemaining;     // 基础剩余积分
+    private Double contribSubtotal;    // 贡献积分汇总(含扣除)
+    private Double contribDeduction;   // 贡献-扣除积分
+    private Double contribExchange;    // 贡献已兑换积分
+    private Double contribRemaining;   // 贡献剩余积分
 
     // 查询条件
     private String beginDate;
@@ -66,26 +66,26 @@ public class WkPointSnapshotSummary extends DataEntity<WkPointSnapshotSummary> {
     public Integer getUploadCount() { return uploadCount; }
     public void setUploadCount(Integer uploadCount) { this.uploadCount = uploadCount; }
 
-    public Integer getBasicSubtotal() { return basicSubtotal; }
-    public void setBasicSubtotal(Integer basicSubtotal) { this.basicSubtotal = basicSubtotal; }
+    public Double getBasicSubtotal() { return basicSubtotal; }
+    public void setBasicSubtotal(Double basicSubtotal) { this.basicSubtotal = basicSubtotal; }
 
-    public Integer getBasicExchange() { return basicExchange; }
-    public void setBasicExchange(Integer basicExchange) { this.basicExchange = basicExchange; }
+    public Double getBasicExchange() { return basicExchange; }
+    public void setBasicExchange(Double basicExchange) { this.basicExchange = basicExchange; }
 
-    public Integer getBasicRemaining() { return basicRemaining; }
-    public void setBasicRemaining(Integer basicRemaining) { this.basicRemaining = basicRemaining; }
+    public Double getBasicRemaining() { return basicRemaining; }
+    public void setBasicRemaining(Double basicRemaining) { this.basicRemaining = basicRemaining; }
 
-    public Integer getContribSubtotal() { return contribSubtotal; }
-    public void setContribSubtotal(Integer contribSubtotal) { this.contribSubtotal = contribSubtotal; }
+    public Double getContribSubtotal() { return contribSubtotal; }
+    public void setContribSubtotal(Double contribSubtotal) { this.contribSubtotal = contribSubtotal; }
 
-    public Integer getContribDeduction() { return contribDeduction; }
-    public void setContribDeduction(Integer contribDeduction) { this.contribDeduction = contribDeduction; }
+    public Double getContribDeduction() { return contribDeduction; }
+    public void setContribDeduction(Double contribDeduction) { this.contribDeduction = contribDeduction; }
 
-    public Integer getContribExchange() { return contribExchange; }
-    public void setContribExchange(Integer contribExchange) { this.contribExchange = contribExchange; }
+    public Double getContribExchange() { return contribExchange; }
+    public void setContribExchange(Double contribExchange) { this.contribExchange = contribExchange; }
 
-    public Integer getContribRemaining() { return contribRemaining; }
-    public void setContribRemaining(Integer contribRemaining) { this.contribRemaining = contribRemaining; }
+    public Double getContribRemaining() { return contribRemaining; }
+    public void setContribRemaining(Double contribRemaining) { this.contribRemaining = contribRemaining; }
 
     public String getBeginDate() { return beginDate; }
     public void setBeginDate(String beginDate) { this.beginDate = beginDate; }

+ 18 - 18
src/main/java/com/jeeplus/modules/WorkKnowledgeBase/entity/WorkKnowledgeBasePoint.java

@@ -41,7 +41,7 @@ public class WorkKnowledgeBasePoint extends DataEntity<WorkKnowledgeBasePoint> {
 	private String phone;
 
 	/** 总积分 */
-	private Integer totalPoint;
+	private Double totalPoint;
 	/** 积分类型 */
 	private String columnId;
 
@@ -50,7 +50,7 @@ public class WorkKnowledgeBasePoint extends DataEntity<WorkKnowledgeBasePoint> {
 	private Date gainEndDate;
 
 	/** 基础积分(当前可用) */
-	private Integer basicPoint;
+	private Double basicPoint;
 
 	/** 贡献积分(当前可用) */
 	private Integer contributionPoint;
@@ -62,13 +62,13 @@ public class WorkKnowledgeBasePoint extends DataEntity<WorkKnowledgeBasePoint> {
 	private Integer exchangedContributionPoint;
 
 	/** 基础积分剩余 */
-	private Integer remainingBasicPoint;
+	private Double remainingBasicPoint;
 
 	/** 贡献积分剩余 */
 	private Integer remainingContributionPoint;
 
 	/** 原始基础积分(兑换前,用于显示可兑换积分) */
-	private Integer originalBasicPoint;
+	private Double originalBasicPoint;
 
 	/** 原始贡献积分(兑换前,用于显示可兑换积分) */
 	private Integer originalContributionPoint;
@@ -89,10 +89,10 @@ public class WorkKnowledgeBasePoint extends DataEntity<WorkKnowledgeBasePoint> {
 	private Integer auditPoint;
 
 	/** 阅读积分额度 */
-	private Integer readPoint;
+	private Double readPoint;
 
 	/** 点赞积分额度 */
-	private Integer likePoint;
+	private Double likePoint;
 
 	/** 兑换积分额度(绝对值) */
 	private Integer exchangePoint;
@@ -234,11 +234,11 @@ public class WorkKnowledgeBasePoint extends DataEntity<WorkKnowledgeBasePoint> {
 		this.phone = phone;
 	}
 
-	public Integer getTotalPoint() {
+	public Double getTotalPoint() {
 		return totalPoint;
 	}
 
-	public void setTotalPoint(Integer totalPoint) {
+	public void setTotalPoint(Double totalPoint) {
 		this.totalPoint = totalPoint;
 	}
 
@@ -274,11 +274,11 @@ public class WorkKnowledgeBasePoint extends DataEntity<WorkKnowledgeBasePoint> {
 		this.gainEndDate = gainEndDate;
 	}
 
-	public Integer getBasicPoint() {
+	public Double getBasicPoint() {
 		return basicPoint;
 	}
 
-	public void setBasicPoint(Integer basicPoint) {
+	public void setBasicPoint(Double basicPoint) {
 		this.basicPoint = basicPoint;
 	}
 
@@ -306,11 +306,11 @@ public class WorkKnowledgeBasePoint extends DataEntity<WorkKnowledgeBasePoint> {
 		this.exchangedContributionPoint = exchangedContributionPoint;
 	}
 
-	public Integer getRemainingBasicPoint() {
+	public Double getRemainingBasicPoint() {
 		return remainingBasicPoint;
 	}
 
-	public void setRemainingBasicPoint(Integer remainingBasicPoint) {
+	public void setRemainingBasicPoint(Double remainingBasicPoint) {
 		this.remainingBasicPoint = remainingBasicPoint;
 	}
 
@@ -322,11 +322,11 @@ public class WorkKnowledgeBasePoint extends DataEntity<WorkKnowledgeBasePoint> {
 		this.remainingContributionPoint = remainingContributionPoint;
 	}
 
-	public Integer getOriginalBasicPoint() {
+	public Double getOriginalBasicPoint() {
 		return originalBasicPoint;
 	}
 
-	public void setOriginalBasicPoint(Integer originalBasicPoint) {
+	public void setOriginalBasicPoint(Double originalBasicPoint) {
 		this.originalBasicPoint = originalBasicPoint;
 	}
 
@@ -378,19 +378,19 @@ public class WorkKnowledgeBasePoint extends DataEntity<WorkKnowledgeBasePoint> {
 		this.auditPoint = auditPoint;
 	}
 
-	public Integer getReadPoint() {
+	public Double getReadPoint() {
 		return readPoint;
 	}
 
-	public void setReadPoint(Integer readPoint) {
+	public void setReadPoint(Double readPoint) {
 		this.readPoint = readPoint;
 	}
 
-	public Integer getLikePoint() {
+	public Double getLikePoint() {
 		return likePoint;
 	}
 
-	public void setLikePoint(Integer likePoint) {
+	public void setLikePoint(Double likePoint) {
 		this.likePoint = likePoint;
 	}
 

+ 4 - 4
src/main/java/com/jeeplus/modules/WorkKnowledgeBase/entity/WorkKnowledgeBasePointDetail.java

@@ -25,8 +25,8 @@ public class WorkKnowledgeBasePointDetail extends DataEntity<WorkKnowledgeBasePo
     /** 获取方式规则ID(关联 work_knowledge_base_point_rule.id) */
     private String ruleId;
 
-    /** 积分值 */
-    private Integer point;
+    /** 积分值(支持小数,如0.5) */
+    private Double point;
 
     /** 是否手动赋分(0否 1是) */
     private String isManualScore;
@@ -86,11 +86,11 @@ public class WorkKnowledgeBasePointDetail extends DataEntity<WorkKnowledgeBasePo
         this.ruleId = ruleId;
     }
 
-    public Integer getPoint() {
+    public Double getPoint() {
         return point;
     }
 
-    public void setPoint(Integer point) {
+    public void setPoint(Double point) {
         this.point = point;
     }
 

+ 2 - 2
src/main/java/com/jeeplus/modules/WorkKnowledgeBase/entity/WorkKnowledgeBaseViolationRecord.java

@@ -21,13 +21,13 @@ public class WorkKnowledgeBaseViolationRecord extends DataEntity<WorkKnowledgeBa
     /** 处理方式: invalid=作废, return=退回 */
     private String handleType;
 
-    /** 原获得积分数 */
+    /** 原获得积分数(创建积分为整数) */
     private Integer originalPoints;
 
     /** 扣积分倍数(0=不扣分, 1=1倍, 2=2倍...) */
     private java.math.BigDecimal pointMultiplier;
 
-    /** 实际扣除积分数(负数) */
+    /** 实际扣除积分数(负数,四舍五入取整) */
     private Integer deductedPoints;
 
     /** 处理原因 */

+ 60 - 53
src/main/java/com/jeeplus/modules/WorkKnowledgeBase/service/WkPointSnapshotService.java

@@ -150,8 +150,8 @@ public class WkPointSnapshotService {
                     .collect(Collectors.toList());
 
             // 4. 按rule分组积分
-            Map<String, Map<String, Integer>> pointsByRule = new HashMap<>();
-            Map<String, Integer> deductionByUser = new HashMap<>();
+            Map<String, Map<String, Double>> pointsByRule = new HashMap<>();
+            Map<String, Double> deductionByUser = new HashMap<>();
             if (!userIds.isEmpty()) {
                 List<Map<String, Object>> ruleResults =
                         pointDetailService.sumPointsByRuleGrouped(userIds, beginDate, endDate);
@@ -159,9 +159,9 @@ public class WkPointSnapshotService {
                     String uid = (String) r.get("userId");
                     String catId = String.valueOf(r.get("categoryId"));
                     String rid = String.valueOf(r.get("ruleId"));
-                    int pts = ((Number) r.get("totalPoint")).intValue();
+                    double pts = ((Number) r.get("totalPoint")).doubleValue();
                     if ("10".equals(catId)) {
-                        deductionByUser.merge(uid, pts, Integer::sum);
+                        deductionByUser.merge(uid, pts, Double::sum);
                     } else {
                         pointsByRule.computeIfAbsent(uid, k -> new HashMap<>()).put(rid, pts);
                     }
@@ -230,15 +230,15 @@ public class WkPointSnapshotService {
             }
 
             // 6. 计算基础积分各L2叶子分类的积分(从pointsByRule按规则汇总)
-            Map<String, Map<String, Integer>> basicL2PointsByUser = new HashMap<>();
-            for (Map.Entry<String, Map<String, Integer>> entry : pointsByRule.entrySet()) {
+            Map<String, Map<String, Double>> basicL2PointsByUser = new HashMap<>();
+            for (Map.Entry<String, Map<String, Double>> entry : pointsByRule.entrySet()) {
                 String uid = entry.getKey();
-                Map<String, Integer> userRulePoints = entry.getValue();
-                Map<String, Integer> l2Points = new LinkedHashMap<>();
+                Map<String, Double> userRulePoints = entry.getValue();
+                Map<String, Double> l2Points = new LinkedHashMap<>();
                 // directRule类型
                 for (Map.Entry<Integer, String> drEntry : basicDirectRuleMap.entrySet()) {
                     String ruleId = drEntry.getValue();
-                    int pts = userRulePoints.getOrDefault(ruleId, 0);
+                    double pts = userRulePoints.getOrDefault(ruleId, 0.0);
                     l2Points.put("direct_" + drEntry.getKey(), pts);
                 }
                 // l2leaf类型
@@ -246,9 +246,9 @@ public class WkPointSnapshotService {
                     String catId = l2Entry.getValue();
                     // 查询该L2分类下的所有规则ID并求和
                     List<WorkKnowledgeBasePointRule> catRules = pointRuleDao.findEnabledByCategoryId(catId);
-                    int total = 0;
+                    double total = 0;
                     for (WorkKnowledgeBasePointRule r : catRules) {
-                        total += userRulePoints.getOrDefault(r.getId(), 0);
+                        total += userRulePoints.getOrDefault(r.getId(), 0.0);
                     }
                     l2Points.put("l2leaf_" + l2Entry.getKey(), total);
                 }
@@ -278,23 +278,23 @@ public class WkPointSnapshotService {
             }
             // 打印第一个用户的 pointsByRule 数据,便于对比
             if (!pointsByRule.isEmpty()) {
-                Map.Entry<String, Map<String, Integer>> firstUser = pointsByRule.entrySet().iterator().next();
+                Map.Entry<String, Map<String, Double>> firstUser = pointsByRule.entrySet().iterator().next();
                 logger.info("用户 {} 的积分规则数据:", firstUser.getKey());
-                for (Map.Entry<String, Integer> rp : firstUser.getValue().entrySet()) {
+                for (Map.Entry<String, Double> rp : firstUser.getValue().entrySet()) {
                     Integer mappedField = contribRuleIdToField.get(rp.getKey());
                     logger.info("  ruleId={}, 积分={}, 映射field={}", rp.getKey(), rp.getValue(), mappedField != null ? mappedField : "未匹配!");
                 }
             }
 
             // 7. 兑换积分
-            Map<String, Map<String, Integer>> exchangeByL1 = new HashMap<>();
+            Map<String, Map<String, Double>> exchangeByL1 = new HashMap<>();
             if (!userIds.isEmpty()) {
                 List<Map<String, Object>> exResults =
                         pointDetailService.sumExchangeByFirstLevelCategory(userIds, beginDate, endDate);
                 for (Map<String, Object> r : exResults) {
                     String uid = (String) r.get("userId");
                     String lid = String.valueOf(r.get("firstLevelId"));
-                    int pts = ((Number) r.get("totalPoint")).intValue();
+                    double pts = ((Number) r.get("totalPoint")).doubleValue();
                     exchangeByL1.computeIfAbsent(uid, k -> new HashMap<>()).put(lid, pts);
                 }
             }
@@ -328,28 +328,28 @@ public class WkPointSnapshotService {
                 info.setUploadCount(uploadCountMap.getOrDefault(uid, 0));
 
                 // field1~fieldN: 基础积分各L2叶子分类(如阅读、点赞)
-                Map<String, Integer> userBasicL2 = basicL2PointsByUser.getOrDefault(uid, Collections.emptyMap());
-                int basicSubtotal = 0;
+                Map<String, Double> userBasicL2 = basicL2PointsByUser.getOrDefault(uid, Collections.emptyMap());
+                double basicSubtotal = 0;
                 int fieldIdx = 1;
-                for (Map.Entry<String, Integer> l2Entry : userBasicL2.entrySet()) {
-                    setField(info, fieldIdx, String.valueOf(l2Entry.getValue()));
+                for (Map.Entry<String, Double> l2Entry : userBasicL2.entrySet()) {
+                    setField(info, fieldIdx, formatPointValue(l2Entry.getValue()));
                     basicSubtotal += l2Entry.getValue();
                     fieldIdx++;
                 }
 
                 // field3~fieldN: 贡献积分各规则(使用headerStructure中的实际ruleId)
-                Map<String, Integer> userRulePoints = pointsByRule.getOrDefault(uid, Collections.emptyMap());
-                int contribSubtotalFromRules = 0;
-                for (Map.Entry<String, Integer> ruleEntry : userRulePoints.entrySet()) {
+                Map<String, Double> userRulePoints = pointsByRule.getOrDefault(uid, Collections.emptyMap());
+                double contribSubtotalFromRules = 0;
+                for (Map.Entry<String, Double> ruleEntry : userRulePoints.entrySet()) {
                     Integer fieldNum = contribRuleIdToField.get(ruleEntry.getKey());
                     if (fieldNum != null && fieldNum >= 3) {
-                        setField(info, fieldNum, String.valueOf(ruleEntry.getValue()));
+                        setField(info, fieldNum, formatPointValue(ruleEntry.getValue()));
                         contribSubtotalFromRules += ruleEntry.getValue();
                     }
                 }
 
                 // field15: 扣除积分
-                info.setField15(String.valueOf(deductionByUser.getOrDefault(uid, 0)));
+                info.setField15(formatPointValue(deductionByUser.getOrDefault(uid, 0.0)));
 
                 // 日志:第一个员工的field3-14值
                 if (employeeList.indexOf(emp) == 0) {
@@ -362,11 +362,11 @@ public class WkPointSnapshotService {
                 snapshotInfoDao.insert(info);
 
                 // 同时生成 summary 员工级记录
-                int contribSubtotal = contribSubtotalFromRules + deductionByUser.getOrDefault(uid, 0);
+                double contribSubtotal = contribSubtotalFromRules + deductionByUser.getOrDefault(uid, 0.0);
                 String basicL1Id = "1";
                 String contribL1Id = "2";
-                int basicExchange = getExchangeValue(exchangeByL1, uid, basicL1Id);
-                int contribExchange = getExchangeValue(exchangeByL1, uid, contribL1Id);
+                double basicExchange = getExchangeValue(exchangeByL1, uid, basicL1Id);
+                double contribExchange = getExchangeValue(exchangeByL1, uid, contribL1Id);
 
                 WkPointSnapshotSummary empSummary = new WkPointSnapshotSummary();
                 empSummary.setId(IdGen.uuid());
@@ -384,7 +384,7 @@ public class WkPointSnapshotService {
                 empSummary.setBasicExchange(basicExchange);
                 empSummary.setBasicRemaining(basicSubtotal - basicExchange);
                 empSummary.setContribSubtotal(contribSubtotal);
-                empSummary.setContribDeduction(deductionByUser.getOrDefault(uid, 0));
+                empSummary.setContribDeduction(deductionByUser.getOrDefault(uid, 0.0));
                 empSummary.setContribExchange(contribExchange);
                 empSummary.setContribRemaining(contribSubtotal - contribExchange);
                 snapshotSummaryDao.insert(empSummary);
@@ -401,21 +401,21 @@ public class WkPointSnapshotService {
                 String officeId = deptEmps.get(0).getOfficeId();
 
                 int totalUpload = deptEmps.stream().mapToInt(e -> uploadCountMap.getOrDefault(e.getUserId(), 0)).sum();
-                int totalBasicSubtotal = deptEmps.stream().mapToInt(e -> {
-                    Map<String, Integer> l2p = basicL2PointsByUser.getOrDefault(e.getUserId(), Collections.emptyMap());
-                    return l2p.values().stream().mapToInt(Integer::intValue).sum();
+                double totalBasicSubtotal = deptEmps.stream().mapToDouble(e -> {
+                    Map<String, Double> l2p = basicL2PointsByUser.getOrDefault(e.getUserId(), Collections.emptyMap());
+                    return l2p.values().stream().mapToDouble(Double::doubleValue).sum();
                 }).sum();
-                int totalContribSubtotal = deptEmps.stream().mapToInt(e -> {
-                    Map<String, Integer> urp = pointsByRule.getOrDefault(e.getUserId(), Collections.emptyMap());
-                    int sub = 0;
-                    for (Map.Entry<String, Integer> re : urp.entrySet()) {
+                double totalContribSubtotal = deptEmps.stream().mapToDouble(e -> {
+                    Map<String, Double> urp = pointsByRule.getOrDefault(e.getUserId(), Collections.emptyMap());
+                    double sub = 0;
+                    for (Map.Entry<String, Double> re : urp.entrySet()) {
                         if (contribRuleIdToField.containsKey(re.getKey())) sub += re.getValue();
                     }
-                    return sub + deductionByUser.getOrDefault(e.getUserId(), 0);
+                    return sub + deductionByUser.getOrDefault(e.getUserId(), 0.0);
                 }).sum();
-                int totalBasicExchange = deptEmps.stream().mapToInt(e -> getExchangeValue(exchangeByL1, e.getUserId(), "1")).sum();
-                int totalContribExchange = deptEmps.stream().mapToInt(e -> getExchangeValue(exchangeByL1, e.getUserId(), "2")).sum();
-                int totalContribDeduction = deptEmps.stream().mapToInt(e -> deductionByUser.getOrDefault(e.getUserId(), 0)).sum();
+                double totalBasicExchange = deptEmps.stream().mapToDouble(e -> getExchangeValue(exchangeByL1, e.getUserId(), "1")).sum();
+                double totalContribExchange = deptEmps.stream().mapToDouble(e -> getExchangeValue(exchangeByL1, e.getUserId(), "2")).sum();
+                double totalContribDeduction = deptEmps.stream().mapToDouble(e -> deductionByUser.getOrDefault(e.getUserId(), 0.0)).sum();
 
                 WkPointSnapshotSummary deptSummary = new WkPointSnapshotSummary();
                 deptSummary.setId(IdGen.uuid());
@@ -439,21 +439,21 @@ public class WkPointSnapshotService {
 
             // 11. 生成公司级汇总
             int companyUpload = employeeList.stream().mapToInt(e -> uploadCountMap.getOrDefault(e.getUserId(), 0)).sum();
-            int companyBasicSubtotal = employeeList.stream().mapToInt(e -> {
-                Map<String, Integer> l2p = basicL2PointsByUser.getOrDefault(e.getUserId(), Collections.emptyMap());
-                return l2p.values().stream().mapToInt(Integer::intValue).sum();
+            double companyBasicSubtotal = employeeList.stream().mapToDouble(e -> {
+                Map<String, Double> l2p = basicL2PointsByUser.getOrDefault(e.getUserId(), Collections.emptyMap());
+                return l2p.values().stream().mapToDouble(Double::doubleValue).sum();
             }).sum();
-            int companyContribSubtotal = employeeList.stream().mapToInt(e -> {
-                Map<String, Integer> urp = pointsByRule.getOrDefault(e.getUserId(), Collections.emptyMap());
-                int sub = 0;
-                for (Map.Entry<String, Integer> re : urp.entrySet()) {
+            double companyContribSubtotal = employeeList.stream().mapToDouble(e -> {
+                Map<String, Double> urp = pointsByRule.getOrDefault(e.getUserId(), Collections.emptyMap());
+                double sub = 0;
+                for (Map.Entry<String, Double> re : urp.entrySet()) {
                     if (contribRuleIdToField.containsKey(re.getKey())) sub += re.getValue();
                 }
-                return sub + deductionByUser.getOrDefault(e.getUserId(), 0);
+                return sub + deductionByUser.getOrDefault(e.getUserId(), 0.0);
             }).sum();
-            int companyBasicExchange = employeeList.stream().mapToInt(e -> getExchangeValue(exchangeByL1, e.getUserId(), "1")).sum();
-            int companyContribExchange = employeeList.stream().mapToInt(e -> getExchangeValue(exchangeByL1, e.getUserId(), "2")).sum();
-            int companyContribDeduction = employeeList.stream().mapToInt(e -> deductionByUser.getOrDefault(e.getUserId(), 0)).sum();
+            double companyBasicExchange = employeeList.stream().mapToDouble(e -> getExchangeValue(exchangeByL1, e.getUserId(), "1")).sum();
+            double companyContribExchange = employeeList.stream().mapToDouble(e -> getExchangeValue(exchangeByL1, e.getUserId(), "2")).sum();
+            double companyContribDeduction = employeeList.stream().mapToDouble(e -> deductionByUser.getOrDefault(e.getUserId(), 0.0)).sum();
 
             WkPointSnapshotSummary companySummary = new WkPointSnapshotSummary();
             companySummary.setId(IdGen.uuid());
@@ -481,6 +481,13 @@ public class WkPointSnapshotService {
     }
 
     /**
+     * 格式化积分值:整数值不带小数后缀(如20),小数值保留(如0.5)
+     */
+    private String formatPointValue(double value) {
+        return value == Math.rint(value) ? String.valueOf((long) value) : String.valueOf(value);
+    }
+
+    /**
      * 设置info的field值
      */
     private void setField(WkPointSnapshotInfo info, int fieldNum, String value) {
@@ -511,9 +518,9 @@ public class WkPointSnapshotService {
     /**
      * 获取兑换积分值
      */
-    private int getExchangeValue(Map<String, Map<String, Integer>> exchangeByL1, String userId, String l1Id) {
-        Map<String, Integer> userExchange = exchangeByL1.get(userId);
-        return userExchange != null && userExchange.containsKey(l1Id) ? userExchange.get(l1Id) : 0;
+    private double getExchangeValue(Map<String, Map<String, Double>> exchangeByL1, String userId, String l1Id) {
+        Map<String, Double> userExchange = exchangeByL1.get(userId);
+        return userExchange != null && userExchange.containsKey(l1Id) ? userExchange.get(l1Id) : 0.0;
     }
 
     /**

+ 2 - 2
src/main/java/com/jeeplus/modules/WorkKnowledgeBase/service/WorkKnowledgeBasePointDetailService.java

@@ -98,7 +98,7 @@ public class WorkKnowledgeBasePointDetailService extends CrudService<WorkKnowled
      * @param columnId 分类ID(对应 work_knowledge_point_category.id)
      * @return 积分总和
      */
-    public int sumUserPointByColumnId(String userId, String columnId) {
+    public double sumUserPointByColumnId(String userId, String columnId) {
         return pointDetailDao.sumUserPointByColumnId(userId, columnId);
     }
 
@@ -109,7 +109,7 @@ public class WorkKnowledgeBasePointDetailService extends CrudService<WorkKnowled
      * @param pointType 积分类型(acquire-获取,exchange-兑换,null-全部)
      * @return 积分总和
      */
-    public int sumUserPointByColumnId(String userId, String columnId, String pointType) {
+    public double sumUserPointByColumnId(String userId, String columnId, String pointType) {
         return pointDetailDao.sumUserPointByColumnIdWithPointType(userId, columnId, pointType);
     }
 

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

@@ -46,7 +46,7 @@ public class WorkKnowledgeBasePointExchangeService extends CrudService<WorkKnowl
      * @param userId 用户ID
      * @return 可用基础积分
      */
-    public int getUserBasicPoints(String userId) {
+    public double getUserBasicPoints(String userId) {
         return pointDetailDao.sumUserPointByColumnId(userId, "1");
     }
 
@@ -55,7 +55,7 @@ public class WorkKnowledgeBasePointExchangeService extends CrudService<WorkKnowl
      * @param userId 用户ID
      * @return 可用贡献积分
      */
-    public int getUserContributionPoints(String userId) {
+    public double getUserContributionPoints(String userId) {
         return pointDetailDao.sumUserPointByColumnId(userId, "2");
     }
 
@@ -67,7 +67,7 @@ public class WorkKnowledgeBasePointExchangeService extends CrudService<WorkKnowl
     @Transactional(readOnly = false)
     public String executeBasicPointExchange(String userId) {
         // 1. 获取用户当前可用基础积分
-        int basicPoints = getUserBasicPoints(userId);
+        double basicPoints = getUserBasicPoints(userId);
 
         // 2. 获取用户首次兑换标记
         WorkKnowledgeBaseUserExchangeFlag flag = exchangeFlagDao.getByUserId(userId);
@@ -97,7 +97,7 @@ public class WorkKnowledgeBasePointExchangeService extends CrudService<WorkKnowl
         if (stepValue == null) stepValue = 100;
 
         // 4. 判断是否满足兑换条件并计算可兑换额度
-        int exchangeablePoints = 0;
+        double exchangeablePoints = 0;
         String ruleTypeName = "";
 
         if (isFirstExchange) {
@@ -106,7 +106,7 @@ public class WorkKnowledgeBasePointExchangeService extends CrudService<WorkKnowl
                 return "基础积分不足" + firstThreshold + "分,无法进行首次兑换(当前" + basicPoints + "分)";
             }
             // 可兑换额度 = 向下取整百
-            exchangeablePoints = (basicPoints / stepValue) * stepValue;
+            exchangeablePoints = Math.floor(basicPoints / stepValue) * stepValue;
             ruleTypeName = "首次兑换";
         } else {
             // 非首次兑换:需要 >= 100
@@ -114,7 +114,7 @@ public class WorkKnowledgeBasePointExchangeService extends CrudService<WorkKnowl
                 return "基础积分不足" + nonFirstThreshold + "分,无法进行兑换(当前" + basicPoints + "分)";
             }
             // 可兑换额度 = 向下取整百
-            exchangeablePoints = (basicPoints / stepValue) * stepValue;
+            exchangeablePoints = Math.floor(basicPoints / stepValue) * stepValue;
             ruleTypeName = "非首次兑换";
         }
 
@@ -150,7 +150,7 @@ public class WorkKnowledgeBasePointExchangeService extends CrudService<WorkKnowl
     @Transactional(readOnly = false)
     public String executeContributionPointExchange(String userId) {
         // 1. 获取用户当前可用贡献积分
-        int contributionPoints = getUserContributionPoints(userId);
+        double contributionPoints = getUserContributionPoints(userId);
 
         if (contributionPoints <= 0) {
             return "无可用贡献积分,无法兑换";
@@ -276,11 +276,11 @@ public class WorkKnowledgeBasePointExchangeService extends CrudService<WorkKnowl
         if (stepValue == null) stepValue = 100;
 
         // 记录每个用户的兑换量
-        Map<String, Integer> exchangedBasicMap = new HashMap<>();
-        Map<String, Integer> exchangedContribMap = new HashMap<>();
+        Map<String, Double> exchangedBasicMap = new HashMap<>();
+        Map<String, Double> exchangedContribMap = new HashMap<>();
         // 记录每个用户的原始积分(兑换前的值,用于显示“可兑换积分”)
-        Map<String, Integer> originalBasicMap = new HashMap<>();
-        Map<String, Integer> originalContribMap = new HashMap<>();
+        Map<String, Double> originalBasicMap = new HashMap<>();
+        Map<String, Double> originalContribMap = new HashMap<>();
         // 记录每个用户是否首次兑换(用于计算兑换金额)
         Map<String, Boolean> isFirstExchangeMap = new HashMap<>();
         // 记录参与兑换的用户ID(用于过滤导出列表)
@@ -297,7 +297,7 @@ public class WorkKnowledgeBasePointExchangeService extends CrudService<WorkKnowl
 
                 // === 基础积分兑换 ===
                 if ("basic".equals(exchangeType)) {
-                    int basicPoints = pointDetailDao.sumUserPointByColumnId(userId, "1");
+                    double basicPoints = pointDetailDao.sumUserPointByColumnId(userId, "1");
                     // 记录原始基础积分(兑换前)
                     originalBasicMap.put(userId, basicPoints);
                     
@@ -314,9 +314,9 @@ public class WorkKnowledgeBasePointExchangeService extends CrudService<WorkKnowl
                     boolean isFirstExchange = (flag.getIsFirstExchanged() == 0 || flag.getIsFirstExchanged() == null);
                     isFirstExchangeMap.put(userId, isFirstExchange);
                     int threshold = isFirstExchange ? firstThreshold : nonFirstThreshold;
-                    int basicExchanged = 0;
+                    double basicExchanged = 0;
                     if (basicPoints >= threshold) {
-                        basicExchanged = (basicPoints / stepValue) * stepValue;
+                        basicExchanged = Math.floor(basicPoints / stepValue) * stepValue;
                         if (basicExchanged > 0) {
                             WorkKnowledgeBasePointDetail detail = new WorkKnowledgeBasePointDetail();
                             detail.setId(com.jeeplus.common.utils.IdGen.uuid());
@@ -340,11 +340,11 @@ public class WorkKnowledgeBasePointExchangeService extends CrudService<WorkKnowl
 
                 // === 贡献积分兑换(全额清零) ===
                 if ("contribution".equals(exchangeType)) {
-                    int contributionPoints = pointDetailDao.sumUserPointByColumnId(userId, "2");
+                    double contributionPoints = pointDetailDao.sumUserPointByColumnId(userId, "2");
                     // 记录原始贡献积分(兑换前)
                     originalContribMap.put(userId, contributionPoints);
                     
-                    int contribExchanged = 0;
+                    double contribExchanged = 0;
                     if (contributionPoints > 0) {
                         contribExchanged = contributionPoints;
                         WorkKnowledgeBasePointDetail cpDetail = new WorkKnowledgeBasePointDetail();
@@ -383,32 +383,32 @@ public class WorkKnowledgeBasePointExchangeService extends CrudService<WorkKnowl
                 continue;
             }
             
-            int exBasic = exchangedBasicMap.containsKey(item.getUserId()) ? exchangedBasicMap.get(item.getUserId()) : 0;
-            int exContrib = exchangedContribMap.containsKey(item.getUserId()) ? exchangedContribMap.get(item.getUserId()) : 0;
+            double exBasic = exchangedBasicMap.containsKey(item.getUserId()) ? exchangedBasicMap.get(item.getUserId()) : 0;
+            double exContrib = exchangedContribMap.containsKey(item.getUserId()) ? exchangedContribMap.get(item.getUserId()) : 0;
             // basicPoint/contributionPoint 已是兑换后的剩余值(因为兑换记录的category_id已正确归类)
-            int remainBasic = item.getBasicPoint() != null ? item.getBasicPoint() : 0;
-            int remainContrib = item.getContributionPoint() != null ? item.getContributionPoint() : 0;
+            double remainBasic = item.getBasicPoint() != null ? item.getBasicPoint() : 0;
+            double remainContrib = item.getContributionPoint() != null ? item.getContributionPoint() : 0;
             // 兑换前的原始积分(可兑换积分)
-            int origBasic = originalBasicMap.containsKey(item.getUserId()) ? originalBasicMap.get(item.getUserId()) : 0;
-            int origContrib = originalContribMap.containsKey(item.getUserId()) ? originalContribMap.get(item.getUserId()) : 0;
+            double origBasic = originalBasicMap.containsKey(item.getUserId()) ? originalBasicMap.get(item.getUserId()) : 0;
+            double origContrib = originalContribMap.containsKey(item.getUserId()) ? originalContribMap.get(item.getUserId()) : 0;
 
-            item.setExchangedBasicPoint(exBasic);
-            item.setExchangedContributionPoint(exContrib);
+            item.setExchangedBasicPoint((int) exBasic);
+            item.setExchangedContributionPoint((int) exContrib);
             item.setRemainingBasicPoint(remainBasic);
-            item.setRemainingContributionPoint(remainContrib);
+            item.setRemainingContributionPoint((int) remainContrib);
             // 设置原始积分(可兑换积分)到新字段,不覆盖basicPoint/contributionPoint
             item.setOriginalBasicPoint(origBasic);
-            item.setOriginalContributionPoint(origContrib);
+            item.setOriginalContributionPoint((int) origContrib);
 
             // 计算兑换金额
             boolean isFirst = isFirstExchangeMap.containsKey(item.getUserId()) ? isFirstExchangeMap.get(item.getUserId()) : false;
-            int exchangeAmt;
+            double exchangeAmt;
             if ("basic".equals(exchangeType)) {
                 exchangeAmt = calculateExchangeAmount("basic", exBasic, isFirst);
             } else {
                 exchangeAmt = calculateExchangeAmount("contribution", exContrib, false);
             }
-            item.setExchangeAmount(exchangeAmt);
+            item.setExchangeAmount((int) exchangeAmt);
             
             exportList.add(item);
         }
@@ -451,10 +451,10 @@ public class WorkKnowledgeBasePointExchangeService extends CrudService<WorkKnowl
         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, Double> exchangedBasicMap = new HashMap<>();
+        Map<String, Double> exchangedContribMap = new HashMap<>();
+        Map<String, Double> originalBasicMap = new HashMap<>();
+        Map<String, Double> originalContribMap = new HashMap<>();
         Map<String, Boolean> isFirstExchangeMap = new HashMap<>();
         // 记录参与兑换的用户ID
         java.util.Set<String> exchangedUserIds = new java.util.HashSet<>();
@@ -469,7 +469,7 @@ public class WorkKnowledgeBasePointExchangeService extends CrudService<WorkKnowl
                 }
 
                 // === 基础积分兑换 ===
-                int basicPoints = pointDetailDao.sumUserPointByColumnId(userId, "1");
+                double basicPoints = pointDetailDao.sumUserPointByColumnId(userId, "1");
                 originalBasicMap.put(userId, basicPoints);
 
                 WorkKnowledgeBaseUserExchangeFlag flag = exchangeFlagDao.getByUserId(userId);
@@ -485,9 +485,9 @@ public class WorkKnowledgeBasePointExchangeService extends CrudService<WorkKnowl
                 boolean isFirstExchange = (flag.getIsFirstExchanged() == 0 || flag.getIsFirstExchanged() == null);
                 isFirstExchangeMap.put(userId, isFirstExchange);
                 int threshold = isFirstExchange ? firstThreshold : nonFirstThreshold;
-                int basicExchanged = 0;
+                double basicExchanged = 0;
                 if (basicPoints >= threshold) {
-                    basicExchanged = (basicPoints / stepValue) * stepValue;
+                    basicExchanged = Math.floor(basicPoints / stepValue) * stepValue;
                     if (basicExchanged > 0) {
                         WorkKnowledgeBasePointDetail detail = new WorkKnowledgeBasePointDetail();
                         detail.setId(com.jeeplus.common.utils.IdGen.uuid());
@@ -508,10 +508,10 @@ public class WorkKnowledgeBasePointExchangeService extends CrudService<WorkKnowl
                 exchangedBasicMap.put(userId, basicExchanged);
 
                 // === 贡献积分兑换(全额清零) ===
-                int contributionPoints = pointDetailDao.sumUserPointByColumnId(userId, "2");
+                double contributionPoints = pointDetailDao.sumUserPointByColumnId(userId, "2");
                 originalContribMap.put(userId, contributionPoints);
 
-                int contribExchanged = 0;
+                double contribExchanged = 0;
                 if (contributionPoints > 0) {
                     contribExchanged = contributionPoints;
                     WorkKnowledgeBasePointDetail cpDetail = new WorkKnowledgeBasePointDetail();
@@ -544,23 +544,23 @@ public class WorkKnowledgeBasePointExchangeService extends CrudService<WorkKnowl
                 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;
+            double exBasic = exchangedBasicMap.containsKey(item.getUserId()) ? exchangedBasicMap.get(item.getUserId()) : 0;
+            double exContrib = exchangedContribMap.containsKey(item.getUserId()) ? exchangedContribMap.get(item.getUserId()) : 0;
+            double origBasic = originalBasicMap.containsKey(item.getUserId()) ? originalBasicMap.get(item.getUserId()) : 0;
+            double origContrib = originalContribMap.containsKey(item.getUserId()) ? originalContribMap.get(item.getUserId()) : 0;
 
-            item.setExchangedBasicPoint(exBasic);
-            item.setExchangedContributionPoint(exContrib);
+            item.setExchangedBasicPoint((int) exBasic);
+            item.setExchangedContributionPoint((int) exContrib);
             item.setRemainingBasicPoint(origBasic - exBasic);
-            item.setRemainingContributionPoint(origContrib - exContrib);
+            item.setRemainingContributionPoint((int) (origContrib - exContrib));
             item.setOriginalBasicPoint(origBasic);
-            item.setOriginalContributionPoint(origContrib);
+            item.setOriginalContributionPoint((int) 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);
+            double basicAmt = calculateExchangeAmount("basic", exBasic, isFirst);
+            double contribAmt = calculateExchangeAmount("contribution", exContrib, false);
+            item.setExchangeAmount((int) (basicAmt + contribAmt));
 
             exportList.add(item);
         }
@@ -573,9 +573,9 @@ public class WorkKnowledgeBasePointExchangeService extends CrudService<WorkKnowl
             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);
+            double amtA = a.getExchangeAmount() != null ? a.getExchangeAmount() : 0;
+            double amtB = b.getExchangeAmount() != null ? b.getExchangeAmount() : 0;
+            return Double.compare(amtB, amtA);
         });
 
         return exportList;
@@ -666,10 +666,10 @@ public class WorkKnowledgeBasePointExchangeService extends CrudService<WorkKnowl
 
         // 记录参与预览的用户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<>();
+        Map<String, Double> previewExchangedBasicMap = new HashMap<>();
+        Map<String, Double> previewExchangedContribMap = new HashMap<>();
+        Map<String, Double> previewOriginalBasicMap = new HashMap<>();
+        Map<String, Double> previewOriginalContribMap = new HashMap<>();
         // 记录每个用户是否首次兑换(用于计算兑换金额)
         Map<String, Boolean> previewIsFirstExchangeMap = new HashMap<>();
 
@@ -677,16 +677,16 @@ public class WorkKnowledgeBasePointExchangeService extends CrudService<WorkKnowl
         for (String userId : userIdList) {
             try {
                 if ("basic".equals(exchangeType)) {
-                    int basicPoints = pointDetailDao.sumUserPointByColumnId(userId, "1");
+                    double basicPoints = pointDetailDao.sumUserPointByColumnId(userId, "1");
                     previewOriginalBasicMap.put(userId, basicPoints);
 
                     WorkKnowledgeBaseUserExchangeFlag flag = exchangeFlagDao.getByUserId(userId);
                     boolean isFirstExchange = (flag == null || flag.getIsFirstExchanged() == 0 || flag.getIsFirstExchanged() == null);
                     previewIsFirstExchangeMap.put(userId, isFirstExchange);
                     int threshold = isFirstExchange ? firstThreshold : nonFirstThreshold;
-                    int basicExchanged = 0;
+                    double basicExchanged = 0;
                     if (basicPoints >= threshold) {
-                        basicExchanged = (basicPoints / stepValue) * stepValue;
+                        basicExchanged = Math.floor(basicPoints / stepValue) * stepValue;
                         if (basicExchanged > 0) {
                             previewUserIds.add(userId);
                         }
@@ -695,7 +695,7 @@ public class WorkKnowledgeBasePointExchangeService extends CrudService<WorkKnowl
                 }
 
                 if ("contribution".equals(exchangeType)) {
-                    int contributionPoints = pointDetailDao.sumUserPointByColumnId(userId, "2");
+                    double contributionPoints = pointDetailDao.sumUserPointByColumnId(userId, "2");
                     previewOriginalContribMap.put(userId, contributionPoints);
 
                     if (contributionPoints > 0) {
@@ -722,43 +722,43 @@ public class WorkKnowledgeBasePointExchangeService extends CrudService<WorkKnowl
                 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;
+            double exBasic = previewExchangedBasicMap.containsKey(item.getUserId()) ? previewExchangedBasicMap.get(item.getUserId()) : 0;
+            double exContrib = previewExchangedContribMap.containsKey(item.getUserId()) ? previewExchangedContribMap.get(item.getUserId()) : 0;
+            double currentBasic = item.getBasicPoint() != null ? item.getBasicPoint() : 0;
+            double currentContrib = item.getContributionPoint() != null ? item.getContributionPoint() : 0;
+            double origBasic = previewOriginalBasicMap.containsKey(item.getUserId()) ? previewOriginalBasicMap.get(item.getUserId()) : 0;
+            double origContrib = previewOriginalContribMap.containsKey(item.getUserId()) ? previewOriginalContribMap.get(item.getUserId()) : 0;
 
-            item.setExchangedBasicPoint(exBasic);
-            item.setExchangedContributionPoint(exContrib);
+            item.setExchangedBasicPoint((int) exBasic);
+            item.setExchangedContributionPoint((int) exContrib);
             item.setOriginalBasicPoint(origBasic);
-            item.setOriginalContributionPoint(origContrib);
+            item.setOriginalContributionPoint((int) origContrib);
             // 预览时的剩余 = 当前积分 - 预计兑换量
             item.setRemainingBasicPoint(currentBasic - exBasic);
-            item.setRemainingContributionPoint(currentContrib - exContrib);
+            item.setRemainingContributionPoint((int) (currentContrib - exContrib));
 
             // 计算兑换金额
             boolean isFirst = previewIsFirstExchangeMap.containsKey(item.getUserId()) ? previewIsFirstExchangeMap.get(item.getUserId()) : false;
-            int exchangeAmt;
+            double exchangeAmt;
             if ("basic".equals(exchangeType)) {
                 exchangeAmt = calculateExchangeAmount("basic", exBasic, isFirst);
             } else {
                 exchangeAmt = calculateExchangeAmount("contribution", exContrib, false);
             }
-            item.setExchangeAmount(exchangeAmt);
+            item.setExchangeAmount((int) exchangeAmt);
 
             previewList.add(item);
         }
 
         // 按可兑换积分额度倒序排序
         previewList.sort((a, b) -> {
-            int pointsA = "basic".equals(exchangeType)
+            double pointsA = "basic".equals(exchangeType)
                     ? (a.getOriginalBasicPoint() != null ? a.getOriginalBasicPoint() : 0)
                     : (a.getOriginalContributionPoint() != null ? a.getOriginalContributionPoint() : 0);
-            int pointsB = "basic".equals(exchangeType)
+            double pointsB = "basic".equals(exchangeType)
                     ? (b.getOriginalBasicPoint() != null ? b.getOriginalBasicPoint() : 0)
                     : (b.getOriginalContributionPoint() != null ? b.getOriginalContributionPoint() : 0);
-            return Integer.compare(pointsB, pointsA);
+            return Double.compare(pointsB, pointsA);
         });
 
         return previewList;
@@ -832,7 +832,7 @@ public class WorkKnowledgeBasePointExchangeService extends CrudService<WorkKnowl
      * 基础积分首次兑换:前300积分给500元,超出部分每100积分给100元
      * 基础积分非首次兑换:每100积分给100元
      */
-    public int calculateExchangeAmount(String exchangeType, int exchangedPoints, boolean isFirstExchange) {
+    public double calculateExchangeAmount(String exchangeType, double exchangedPoints, boolean isFirstExchange) {
         if (exchangedPoints <= 0) {
             return 0;
         }
@@ -843,15 +843,15 @@ public class WorkKnowledgeBasePointExchangeService extends CrudService<WorkKnowl
         // 基础积分
         if (isFirstExchange) {
             // 首次兑换:前300积分给500元,超出部分每100积分给100元
-            int amount = 500;
-            int remaining = exchangedPoints - 300;
+            double amount = 500;
+            double remaining = exchangedPoints - 300;
             if (remaining > 0) {
-                amount += (remaining / 100) * 100;
+                amount += Math.floor(remaining / 100) * 100;
             }
             return amount;
         } else {
             // 非首次兑换:每100积分给100元
-            return (exchangedPoints / 100) * 100;
+            return Math.floor(exchangedPoints / 100) * 100;
         }
     }
 }

+ 3 - 3
src/main/java/com/jeeplus/modules/WorkKnowledgeBase/service/WorkKnowledgeBaseReadLikeService.java

@@ -329,7 +329,7 @@ public class WorkKnowledgeBaseReadLikeService extends CrudService<WorkKnowledgeB
             WorkKnowledgeBasePointRule rule = pointRuleDao.findByCategoryIdAndRuleType(categoryId, "10");
             
             if (rule != null && rule.getPointValue() != null) {
-                int pointValue = Integer.parseInt(rule.getPointValue());
+                double pointValue = Double.parseDouble(rule.getPointValue());
                 if (pointValue > 0) {
                     // 插入积分明细(change_type=3 表示阅读积分),给阅读人发放积分
                     insertPointDetail(readerUserId, fileId, 3, categoryId, rule.getId(), pointValue);
@@ -384,7 +384,7 @@ public class WorkKnowledgeBaseReadLikeService extends CrudService<WorkKnowledgeB
             WorkKnowledgeBasePointRule rule = pointRuleDao.findByCategoryIdAndRuleType(categoryId, "20");
             
             if (rule != null && rule.getPointValue() != null) {
-                int pointValue = Integer.parseInt(rule.getPointValue());
+                double pointValue = Double.parseDouble(rule.getPointValue());
                 if (pointValue > 0) {
                     // 插入积分明细(change_type=4 表示点赞积分),给点赞人发放积分
                     insertPointDetail(likerUserId, fileId, 4, categoryId, rule.getId(), pointValue);
@@ -399,7 +399,7 @@ public class WorkKnowledgeBaseReadLikeService extends CrudService<WorkKnowledgeB
     /**
      * 插入积分明细记录,同时确保该用户的兑换标记记录存在
      */
-    private void insertPointDetail(String userId, String shareId, Integer changeType, String categoryId, String ruleId, Integer point) {
+    private void insertPointDetail(String userId, String shareId, Integer changeType, String categoryId, String ruleId, Double point) {
         WorkKnowledgeBasePointDetail detail = new WorkKnowledgeBasePointDetail();
         detail.setUserId(userId);
         detail.setShareId(shareId);

+ 36 - 14
src/main/java/com/jeeplus/modules/WorkKnowledgeBase/service/WorkKnowledgeBaseShareService.java

@@ -1031,18 +1031,18 @@ public class WorkKnowledgeBaseShareService extends CrudService<WorkKnowledgeBase
         }
         
         // ========== 审核浏览行为校验(字典配置最低停留时间 + 必须查看过附件) ==========
-        String minStayStr = com.jeeplus.modules.sys.utils.DictUtils.getDictLabel("1", "audit_min_stay_seconds", "30");
-        int minStaySeconds = 30; // 默认30秒
+        String minStayStr = com.jeeplus.modules.sys.utils.DictUtils.getDictLabel("1", "audit_min_stay_seconds", "180");
+        int minStaySeconds = 180; // 默认3分钟(180秒)
         try {
             minStaySeconds = Integer.parseInt(minStayStr);
         } catch (NumberFormatException e) {
-            minStaySeconds = 30;
+            minStaySeconds = 180;
         }
         if (isViewedAttachment == null || isViewedAttachment != 1) {
-            throw new RuntimeException("您还没有查看附件信息,请认真查看附件内容至少" + minStaySeconds + "秒后再审核");
+            throw new RuntimeException("您还没有查看附件信息,请认真查看附件内容至少" + formatDuration(minStaySeconds) + "后再审核");
         }
         if (viewDurationSeconds != null && viewDurationSeconds < minStaySeconds) {
-            throw new RuntimeException("您查看附件仅" + viewDurationSeconds + "秒,低于最低要求" + minStaySeconds + "秒,请认真查看附件内容后再审核");
+            throw new RuntimeException("您查看附件仅" + formatDuration(viewDurationSeconds) + ",低于最低要求" + formatDuration(minStaySeconds) + ",请认真查看附件内容后再审核");
         }
         
         // 检查本轮是否已审核过(按 audit_start_date 过滤,避免历史记录干扰)
@@ -1765,7 +1765,7 @@ public class WorkKnowledgeBaseShareService extends CrudService<WorkKnowledgeBase
         if (StringUtils.isNotBlank(submitUserId) && averageScore != null && createRule != null) {
             insertPointDetail(submitUserId, shareId, POINT_CHANGE_CREATE, categoryId, createRule.getId(), averageScore);
         }
-        
+            
         // 2、本轮审核人各获得审核积分(使用固定审核积分值)
         if (records == null || records.isEmpty() || auditRule == null || StringUtils.isBlank(auditRule.getPointValue())) {
             return;
@@ -1908,7 +1908,7 @@ public class WorkKnowledgeBaseShareService extends CrudService<WorkKnowledgeBase
     /**
      * 插入一条积分明细记录,同时确保该用户的兑换标记记录存在
      */
-    private void insertPointDetail(String userId, String shareId, Integer changeType, String categoryId, String ruleId, Integer point) {
+    private void insertPointDetail(String userId, String shareId, Integer changeType, String categoryId, String ruleId, int point) {
         WorkKnowledgeBasePointDetail detail = new WorkKnowledgeBasePointDetail();
         detail.setId(IdGen.uuid());
         detail.setUserId(userId);
@@ -1916,7 +1916,7 @@ public class WorkKnowledgeBaseShareService extends CrudService<WorkKnowledgeBase
         detail.setChangeType(changeType);
         detail.setCategoryId(categoryId);
         detail.setRuleId(ruleId);
-        detail.setPoint(point);
+        detail.setPoint((double) point);
         // 非手动赋分,清空手动赋分相关字段
         detail.setIsManualScore("0");
         detail.preInsert();
@@ -1938,7 +1938,7 @@ public class WorkKnowledgeBaseShareService extends CrudService<WorkKnowledgeBase
      * @param targetUserId 被赋分人ID
      * @param manualScoreTime 赋分时间
      */
-    private void insertPointDetailForManualScore(String userId, String shareId, Integer changeType, String categoryId, String ruleId, Integer point,
+    private void insertPointDetailForManualScore(String userId, String shareId, Integer changeType, String categoryId, String ruleId, int point,
                                                    String scoreUserId, String targetUserId, java.util.Date manualScoreTime) {
         WorkKnowledgeBasePointDetail detail = new WorkKnowledgeBasePointDetail();
         detail.setId(IdGen.uuid());
@@ -1947,7 +1947,7 @@ public class WorkKnowledgeBaseShareService extends CrudService<WorkKnowledgeBase
         detail.setChangeType(changeType);
         detail.setCategoryId(categoryId);
         detail.setRuleId(ruleId);
-        detail.setPoint(point);
+        detail.setPoint((double) point);
         // 手动赋分标记
         detail.setIsManualScore("1");
         detail.setManualScoreUserId(scoreUserId);
@@ -3106,10 +3106,10 @@ public class WorkKnowledgeBaseShareService extends CrudService<WorkKnowledgeBase
             throw new RuntimeException("无法确定文件创建人");
         }
 
-        // 计算该文件给目标用户带来的总积分
+        // 计算该文件给目标用户带来的总创建积分(创建积分为整数)
         int totalPoints = calculateFilePointsForUser(fileId, targetUserId);
 
-        // 计算扣除积分
+        // 计算扣除积分(四舍五入取整)
         int deductedPoints = 0;
         if (pointMultiplier != null && pointMultiplier.compareTo(java.math.BigDecimal.ZERO) > 0) {
             deductedPoints = (int) Math.round(totalPoints * pointMultiplier.doubleValue());
@@ -3158,7 +3158,7 @@ public class WorkKnowledgeBaseShareService extends CrudService<WorkKnowledgeBase
             detail.setChangeType(POINT_CHANGE_DEDUCTION);
             detail.setCategoryId(deductionCategoryId); // 扣分标准分类ID
             detail.setRuleId(deductionRuleId); // 违规扣分规则ID
-            detail.setPoint(-deductedPoints);
+            detail.setPoint((double) -deductedPoints);
             detail.setIsDeduction("1");
             detail.setViolationId(record.getId());
             detail.setIsManualScore("0");
@@ -3173,6 +3173,28 @@ public class WorkKnowledgeBaseShareService extends CrudService<WorkKnowledgeBase
     }
 
     /**
+     * 时间格式化:秒 -> "X秒" / "X分Y秒" / "X时Y分Z秒"
+     */
+    private String formatDuration(int seconds) {
+        if (seconds < 60) {
+            return seconds + "秒";
+        } else if (seconds < 3600) {
+            int minutes = seconds / 60;
+            int secs = seconds % 60;
+            return secs == 0 ? minutes + "分钟" : minutes + "分" + secs + "秒";
+        } else {
+            int hours = seconds / 3600;
+            int minutes = (seconds % 3600) / 60;
+            int secs = seconds % 60;
+            StringBuilder sb = new StringBuilder();
+            sb.append(hours).append("小时");
+            if (minutes > 0) sb.append(minutes).append("分");
+            if (secs > 0) sb.append(secs).append("秒");
+            return sb.toString();
+        }
+    }
+
+    /**
      * 计算某个文件给某个用户带来的创建积分(change_type=1)
      */
     private int calculateFilePointsForUser(String fileId, String userId) {
@@ -3186,7 +3208,7 @@ public class WorkKnowledgeBaseShareService extends CrudService<WorkKnowledgeBase
         if (details != null) {
             for (WorkKnowledgeBasePointDetail d : details) {
                 if (d.getPoint() != null && d.getPoint() > 0) {
-                    total += d.getPoint();
+                    total += d.getPoint().intValue();
                 }
             }
         }

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

@@ -193,7 +193,7 @@ public class WorkKnowledgeBasePointController extends BaseController {
         }
         Page<UserPointDetail> page = workKnowledgeBasePointDetailService.findUserPointDetailPage(new Page<>(request, response), userPointDetail);
         // 查询该用户在当前分类(含子节点)下的积分总和(根据积分类型筛选)
-        int totalPoint = workKnowledgeBasePointDetailService.sumUserPointByColumnId(
+        double totalPoint = workKnowledgeBasePointDetailService.sumUserPointByColumnId(
                 userPointDetail.getUserId(), userPointDetail.getColumnId(), userPointDetail.getPointType());
         model.addAttribute("page", page);
         model.addAttribute("userPointDetail", userPointDetail);
@@ -279,10 +279,10 @@ public class WorkKnowledgeBasePointController extends BaseController {
                 int exBasic = item.getExchangedBasicPoint() != null ? item.getExchangedBasicPoint() : 0;
                 int exContrib = item.getExchangedContributionPoint() != null ? item.getExchangedContributionPoint() : 0;
                 // 可兑换积分(兑换前的原始积分)
-                int origBasic = item.getOriginalBasicPoint() != null ? item.getOriginalBasicPoint() : 0;
+                double origBasic = item.getOriginalBasicPoint() != null ? item.getOriginalBasicPoint() : 0;
                 int origContrib = item.getOriginalContributionPoint() != null ? item.getOriginalContributionPoint() : 0;
                 // 兑换后剩余积分
-                int remainBasic = item.getRemainingBasicPoint() != null ? item.getRemainingBasicPoint() : 0;
+                double remainBasic = item.getRemainingBasicPoint() != null ? item.getRemainingBasicPoint() : 0;
                 int remainContrib = item.getRemainingContributionPoint() != null ? item.getRemainingContributionPoint() : 0;
                 // 兑换金额(两类合计)
                 int exchangeAmt = item.getExchangeAmount() != null ? item.getExchangeAmount() : 0;
@@ -298,9 +298,9 @@ public class WorkKnowledgeBasePointController extends BaseController {
                 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++, origBasic, 2, Double.class);
                 exportExcel.addCell(row, col++, exBasic, 2, Integer.class);
-                exportExcel.addCell(row, col++, remainBasic, 2, Integer.class);
+                exportExcel.addCell(row, col++, remainBasic, 2, Double.class);
                 // 兑换金额(元):最后一列
                 exportExcel.addCell(row, col++, exchangeAmt, 2, Integer.class);
             }
@@ -451,9 +451,9 @@ public class WorkKnowledgeBasePointController extends BaseController {
                     .collect(Collectors.toList());
 
             // 4a. 按rule分组积分(包含负数扣分)
-            java.util.Map<String, java.util.Map<String, Integer>> pointsByRule = new java.util.HashMap<>();
+            java.util.Map<String, java.util.Map<String, Double>> pointsByRule = new java.util.HashMap<>();
             // 扣分标准(category_id=10)的积分单独汇总,归入贡献积分小计
-            java.util.Map<String, Integer> deductionByUser = new java.util.HashMap<>();
+            java.util.Map<String, Double> deductionByUser = new java.util.HashMap<>();
             if (!userIds.isEmpty()) {
                 List<java.util.Map<String, Object>> ruleResults =
                         workKnowledgeBasePointDetailService.sumPointsByRuleGrouped(userIds, queryParam.getBeginDate(), queryParam.getEndDate());
@@ -461,21 +461,21 @@ public class WorkKnowledgeBasePointController extends BaseController {
                     String uid = (String) r.get("userId");
                     String catId = String.valueOf(r.get("categoryId"));
                     String rid = String.valueOf(r.get("ruleId"));
-                    int pts = ((Number) r.get("totalPoint")).intValue();
+                    double pts = ((Number) r.get("totalPoint")).doubleValue();
                     if ("10".equals(catId)) {
                         // 扣分标准的积分单独汇总
-                        deductionByUser.merge(uid, pts, Integer::sum);
+                        deductionByUser.merge(uid, pts, Double::sum);
                     } else {
-                        pointsByRule.computeIfAbsent(uid, k -> new java.util.HashMap<>()).merge(rid, pts, Integer::sum);
+                        pointsByRule.computeIfAbsent(uid, k -> new java.util.HashMap<>()).merge(rid, pts, Double::sum);
                     }
                 }
             }
 
-            // 4a-extra. 汇总L2叶子分类的积分(用于无L3子列的L2叶子,如"阅读"、"点赞")
-            java.util.Map<String, java.util.Map<String, Integer>> l2PointsByCategory = new java.util.HashMap<>();
-            for (java.util.Map.Entry<String, java.util.Map<String, Integer>> entry : pointsByRule.entrySet()) {
+            // 4a-extra. 汇总L2叶子分类的积分(用于无L3子列的L2叶子,如“阅读”、“点赞”)
+            java.util.Map<String, java.util.Map<String, Double>> l2PointsByCategory = new java.util.HashMap<>();
+            for (java.util.Map.Entry<String, java.util.Map<String, Double>> entry : pointsByRule.entrySet()) {
                 String uid = entry.getKey();
-                java.util.Map<String, Integer> userRulePoints = entry.getValue();
+                java.util.Map<String, Double> userRulePoints = entry.getValue();
                 for (int i = 0; i < secondLevelCategoryIds.size(); i++) {
                     List<String> catIds = secondLevelCategoryIds.get(i);
                     for (int j = 0; j < catIds.size(); j++) {
@@ -483,9 +483,9 @@ public class WorkKnowledgeBasePointController extends BaseController {
                         if (catId.isEmpty()) continue;
                         // 查询该L2分类下的所有规则ID
                         List<WorkKnowledgeBasePointRule> catRules = pointRuleDao.findEnabledByCategoryId(catId);
-                        int total = 0;
+                        double total = 0;
                         for (WorkKnowledgeBasePointRule r : catRules) {
-                            total += userRulePoints.getOrDefault(r.getId(), 0);
+                            total += userRulePoints.getOrDefault(r.getId(), 0.0);
                         }
                         l2PointsByCategory.computeIfAbsent(uid, k -> new java.util.HashMap<>()).put(catId, total);
                     }
@@ -493,14 +493,14 @@ public class WorkKnowledgeBasePointController extends BaseController {
             }
 
             // 4b. 兑现积分(按L1分类,point<0取绝对值)
-            java.util.Map<String, java.util.Map<String, Integer>> exchangeByL1 = new java.util.HashMap<>();
+            java.util.Map<String, java.util.Map<String, Double>> exchangeByL1 = new java.util.HashMap<>();
             if (!userIds.isEmpty()) {
                 List<java.util.Map<String, Object>> exResults =
                         workKnowledgeBasePointDetailService.sumExchangeByFirstLevelCategory(userIds, queryParam.getBeginDate(), queryParam.getEndDate());
                 for (java.util.Map<String, Object> r : exResults) {
                     String uid = (String) r.get("userId");
                     String lid = String.valueOf(r.get("firstLevelId"));
-                    int pts = ((Number) r.get("totalPoint")).intValue();
+                    double pts = ((Number) r.get("totalPoint")).doubleValue();
                     exchangeByL1.computeIfAbsent(uid, k -> new java.util.HashMap<>()).put(lid, pts);
                 }
             }
@@ -536,18 +536,18 @@ public class WorkKnowledgeBasePointController extends BaseController {
                                 // 直接规则L2(如"基础积分"下的规则),直接从pointsByRule取数据
                                 String ruleId = (i < directRuleIds.size() && j < directRuleIds.get(i).size())
                                         ? directRuleIds.get(i).get(j) : "";
-                                int drVal = emps.stream().mapToInt(e -> {
-                                    java.util.Map<String, Integer> m = pointsByRule.get(e.getUserId());
-                                    return m != null && m.containsKey(ruleId) ? m.get(ruleId) : 0;
+                                double drVal = emps.stream().mapToDouble(e -> {
+                                    java.util.Map<String, Double> m = pointsByRule.get(e.getUserId());
+                                    return m != null && m.containsKey(ruleId) ? m.get(ruleId) : 0.0;
                                 }).sum();
                                 row.put("exchange_" + i + "_" + j, drVal);
                             } else if (l2LeafIndices.contains(i * 1000 + j)) {
                                 // L2叶子列(如"阅读"、"点赞"),使用L2级汇总数据
                                 String catId = (i < secondLevelCategoryIds.size() && j < secondLevelCategoryIds.get(i).size())
                                         ? secondLevelCategoryIds.get(i).get(j) : "";
-                                int leafVal = emps.stream().mapToInt(e -> {
-                                    java.util.Map<String, Integer> m = l2PointsByCategory.get(e.getUserId());
-                                    return m != null && m.containsKey(catId) ? m.get(catId) : 0;
+                                double leafVal = emps.stream().mapToDouble(e -> {
+                                    java.util.Map<String, Double> m = l2PointsByCategory.get(e.getUserId());
+                                    return m != null && m.containsKey(catId) ? m.get(catId) : 0.0;
                                 }).sum();
                                 row.put("exchange_" + i + "_" + j, leafVal);
                             } else if (subtotalIndices.contains(i * 1000 + j)) {
@@ -558,15 +558,15 @@ public class WorkKnowledgeBasePointController extends BaseController {
                                 row.put("remaining_" + i, 0);
                             } else if (deductionIndices.contains(i * 1000 + j)) {
                                 // 扣除积分列(仅贡献积分组),从deductionByUser取数据
-                                int dedVal = emps.stream().mapToInt(e ->
-                                        deductionByUser.getOrDefault(e.getUserId(), 0)
+                                double dedVal = emps.stream().mapToDouble(e ->
+                                        deductionByUser.getOrDefault(e.getUserId(), 0.0)
                                 ).sum();
                                 row.put("exchange_" + i + "_" + j, dedVal);
                             } else {
                                 // 已兑换积分列
-                                int exVal = emps.stream().mapToInt(e -> {
-                                    java.util.Map<String, Integer> m = exchangeByL1.get(e.getUserId());
-                                    return m != null && m.containsKey(l1Id) ? m.get(l1Id) : 0;
+                                double exVal = emps.stream().mapToDouble(e -> {
+                                    java.util.Map<String, Double> m = exchangeByL1.get(e.getUserId());
+                                    return m != null && m.containsKey(l1Id) ? m.get(l1Id) : 0.0;
                                 }).sum();
                                 row.put("exchange_" + i + "_" + j, exVal);
                             }
@@ -576,16 +576,16 @@ public class WorkKnowledgeBasePointController extends BaseController {
                                         && k < dataKeysL3.get(i).get(j).size())
                                         ? dataKeysL3.get(i).get(j).get(k) : "";
                                 String ruleId = ruleKey.startsWith("rule_") ? ruleKey.substring(5) : "";
-                                int ruleVal = emps.stream().mapToInt(e -> {
-                                    java.util.Map<String, Integer> m = pointsByRule.get(e.getUserId());
-                                    return m != null && m.containsKey(ruleId) ? m.get(ruleId) : 0;
+                                double ruleVal = emps.stream().mapToDouble(e -> {
+                                    java.util.Map<String, Double> m = pointsByRule.get(e.getUserId());
+                                    return m != null && m.containsKey(ruleId) ? m.get(ruleId) : 0.0;
                                 }).sum();
                                 row.put("rule_" + i + "_" + j + "_" + k, ruleVal);
                             }
                         }
                     }
                     // 小计 = 所有规则列之和 + L2叶子列之和 + 直接规则列之和(不含汇总、已兑换、未兑换)
-                    int subtotal = 0;
+                    double subtotal = 0;
                     for (int j = 0; j < l2ForL1.size(); j++) {
                         List<String> l3ForL2 = l3ForL1.get(j);
                         if (subtotalIndices.contains(i * 1000 + j) || remainingIndices.contains(i * 1000 + j)) {
@@ -594,12 +594,12 @@ public class WorkKnowledgeBasePointController extends BaseController {
                         } else if (directRuleIndices.contains(i * 1000 + j) || l2LeafIndices.contains(i * 1000 + j) || deductionIndices.contains(i * 1000 + j)) {
                             // 直接规则L2、L2叶子列、扣除积分列,直接取值
                             Object v = row.get("exchange_" + i + "_" + j);
-                            if (v instanceof Number) subtotal += ((Number) v).intValue();
+                            if (v instanceof Number) subtotal += ((Number) v).doubleValue();
                         } else if (!l3ForL2.isEmpty()) {
                             // 有L3的规则列
                             for (int k = 0; k < l3ForL2.size(); k++) {
                                 Object v = row.get("rule_" + i + "_" + j + "_" + k);
-                                if (v instanceof Number) subtotal += ((Number) v).intValue();
+                                if (v instanceof Number) subtotal += ((Number) v).doubleValue();
                             }
                         }
                         // 注意:已兑换积分列不计入小计
@@ -607,11 +607,11 @@ public class WorkKnowledgeBasePointController extends BaseController {
                     row.put("subtotal_" + i, subtotal);
                     // 剩余积分 = 积分汇总 - 已兑换积分
                     Integer exColIdx = exchangeColumnIndexMap.get(i);
-                    int exVal = 0;
+                    double exVal = 0;
                     if (exColIdx != null) {
                         Object v = row.get("exchange_" + i + "_" + exColIdx);
                         if (v instanceof Number) {
-                            exVal = ((Number) v).intValue();
+                            exVal = ((Number) v).doubleValue();
                         }
                     }
                     row.put("remaining_" + i, subtotal - exVal);
@@ -704,26 +704,26 @@ public class WorkKnowledgeBasePointController extends BaseController {
             // 查询所有员工快照明细,聚合贡献积分各列(field3-field14)
             List<WkPointSnapshotInfo> allInfos = wkPointSnapshotService.getAllEmployeeInfos(year, month);
             // 公司级聚合(field1~field15全部聚合)
-            Map<String, Integer> companyContrib = new LinkedHashMap<>();
-            for (int f = 1; f <= 15; f++) companyContrib.put("field" + f, 0);
+            Map<String, Double> companyContrib = new LinkedHashMap<>();
+            for (int f = 1; f <= 15; f++) companyContrib.put("field" + f, 0.0);
             for (WkPointSnapshotInfo info : allInfos) {
                 for (int f = 1; f <= 15; f++) {
                     String val = getFieldValue(info, f);
-                    companyContrib.merge("field" + f, parseInt(val), Integer::sum);
+                    companyContrib.merge("field" + f, parseDouble(val), Double::sum);
                 }
             }
             // 部门级聚合(按officeId分组)
-            Map<String, Map<String, Integer>> deptContribMap = new LinkedHashMap<>();
+            Map<String, Map<String, Double>> deptContribMap = new LinkedHashMap<>();
             for (WkPointSnapshotInfo info : allInfos) {
                 String oid = info.getOfficeId() != null ? info.getOfficeId() : "";
-                Map<String, Integer> deptContrib = deptContribMap.computeIfAbsent(oid, k -> {
-                    Map<String, Integer> m = new LinkedHashMap<>();
-                    for (int f = 1; f <= 15; f++) m.put("field" + f, 0);
+                Map<String, Double> deptContrib = deptContribMap.computeIfAbsent(oid, k -> {
+                    Map<String, Double> m = new LinkedHashMap<>();
+                    for (int f = 1; f <= 15; f++) m.put("field" + f, 0.0);
                     return m;
                 });
                 for (int f = 1; f <= 15; f++) {
                     String val = getFieldValue(info, f);
-                    deptContrib.merge("field" + f, parseInt(val), Integer::sum);
+                    deptContrib.merge("field" + f, parseDouble(val), Double::sum);
                 }
             }
 
@@ -771,9 +771,9 @@ public class WorkKnowledgeBasePointController extends BaseController {
         }
     }
 
-    private int parseInt(String val) {
+    private double parseDouble(String val) {
         if (val == null || val.isEmpty()) return 0;
-        try { return Integer.parseInt(val); } catch (NumberFormatException e) { return 0; }
+        try { return Double.parseDouble(val); } catch (NumberFormatException e) { return 0; }
     }
 
     /**
@@ -1098,13 +1098,13 @@ public class WorkKnowledgeBasePointController extends BaseController {
 
             int rank = 1;
             for (WorkKnowledgeBasePoint item : rankingList) {
-                int basicEarned = item.getBasicPoint() != null ? item.getBasicPoint() : 0;
+                double basicEarned = item.getBasicPoint() != null ? item.getBasicPoint() : 0;
                 int basicExchanged = item.getExchangedBasicPoint() != null ? item.getExchangedBasicPoint() : 0;
-                int basicRemaining = item.getRemainingBasicPoint() != null ? item.getRemainingBasicPoint() : 0;
+                double basicRemaining = item.getRemainingBasicPoint() != null ? item.getRemainingBasicPoint() : 0;
                 int contribEarned = item.getContributionPoint() != null ? item.getContributionPoint() : 0;
                 int contribExchanged = item.getExchangedContributionPoint() != null ? item.getExchangedContributionPoint() : 0;
                 int contribRemaining = item.getRemainingContributionPoint() != null ? item.getRemainingContributionPoint() : 0;
-                int totalEarned = item.getTotalPoint() != null ? item.getTotalPoint() : 0;
+                double totalEarned = item.getTotalPoint() != null ? item.getTotalPoint() : 0;
 
                 org.apache.poi.ss.usermodel.Row row = exportExcel.addRow();
                 int col = 0;
@@ -1120,18 +1120,18 @@ public class WorkKnowledgeBasePointController extends BaseController {
                         exportExcel.addCell(row, col++, contribRemaining, 2, Integer.class);
                         break;
                     case "basic":
-                        exportExcel.addCell(row, col++, basicEarned, 2, Integer.class);
+                        exportExcel.addCell(row, col++, basicEarned, 2, Double.class);
                         exportExcel.addCell(row, col++, basicExchanged, 2, Integer.class);
-                        exportExcel.addCell(row, col++, basicRemaining, 2, Integer.class);
+                        exportExcel.addCell(row, col++, basicRemaining, 2, Double.class);
                         break;
                     default:
-                        exportExcel.addCell(row, col++, basicEarned, 2, Integer.class);
+                        exportExcel.addCell(row, col++, basicEarned, 2, Double.class);
                         exportExcel.addCell(row, col++, basicExchanged, 2, Integer.class);
-                        exportExcel.addCell(row, col++, basicRemaining, 2, Integer.class);
+                        exportExcel.addCell(row, col++, basicRemaining, 2, Double.class);
                         exportExcel.addCell(row, col++, contribEarned, 2, Integer.class);
                         exportExcel.addCell(row, col++, contribExchanged, 2, Integer.class);
                         exportExcel.addCell(row, col++, contribRemaining, 2, Integer.class);
-                        exportExcel.addCell(row, col++, totalEarned, 2, Integer.class);
+                        exportExcel.addCell(row, col++, totalEarned, 2, Double.class);
                         break;
                 }
             }

+ 4 - 4
src/main/java/com/jeeplus/modules/WorkKnowledgeBase/web/WorkKnowledgeBaseShareController.java

@@ -391,12 +391,12 @@ public class WorkKnowledgeBaseShareController extends BaseController {
         }
 
         // 传递审核最低停留时间字典值(用于前端校验)
-        String minStayStr = com.jeeplus.modules.sys.utils.DictUtils.getDictLabel("1", "audit_min_stay_seconds", "30");
-        int minStaySeconds = 30;
+        String minStayStr = com.jeeplus.modules.sys.utils.DictUtils.getDictLabel("1", "audit_min_stay_seconds", "180");
+        int minStaySeconds = 180;
         try {
             minStaySeconds = Integer.parseInt(minStayStr);
         } catch (NumberFormatException e) {
-            minStaySeconds = 30;
+            minStaySeconds = 180;
         }
         model.addAttribute("minStaySeconds", minStaySeconds);
 
@@ -2185,7 +2185,7 @@ public class WorkKnowledgeBaseShareController extends BaseController {
             if (details != null) {
                 for (com.jeeplus.modules.WorkKnowledgeBase.entity.WorkKnowledgeBasePointDetail d : details) {
                     if (d.getPoint() != null && d.getPoint() > 0) {
-                        originalPoints += d.getPoint();
+                        originalPoints += d.getPoint().intValue();
                     }
                 }
             }

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

@@ -34,7 +34,7 @@
             IFNULL(d.share_id, '')    AS "shareId",
             d.category_id AS "categoryId",
             d.rule_id     AS "ruleId",
-            CAST(IFNULL(d.point, 0) AS SIGNED) AS "point",
+            IFNULL(d.point, 0) AS "point",
             d.create_date AS "pointCreateDate",
             IFNULL(s.name, '')          AS "shareName",
             IFNULL(s.tree_node_id, '')  AS "treeNodeId",

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

@@ -245,7 +245,7 @@
             IFNULL(d.share_id, '')  AS "shareId",
             d.category_id AS "categoryId",
             d.rule_id     AS "ruleId",
-            CAST(IFNULL(d.point, 0) AS SIGNED) AS "point",
+            IFNULL(d.point, 0) AS "point",
             d.create_date AS "createDate",
             IFNULL(s.name, '')          AS "shareName",
             IFNULL(s.tree_node_id, '')  AS "treeNodeId",
@@ -337,7 +337,7 @@
     </select>
     
     <!-- 根据用户ID和分类ID(含子节点)统计积分总和 -->
-    <select id="sumUserPointByColumnId" resultType="java.lang.Integer">
+    <select id="sumUserPointByColumnId" resultType="java.lang.Double">
         SELECT COALESCE(SUM(d.point), 0)
         FROM work_knowledge_base_point_detail d
         LEFT JOIN work_knowledge_point_category c ON c.id = d.category_id AND c.del_flag = '0'
@@ -351,7 +351,7 @@
     </select>
 
     <!-- 根据用户ID、分类ID和积分类型统计积分总和(支持pointType筛选) -->
-    <select id="sumUserPointByColumnIdWithPointType" resultType="java.lang.Integer">
+    <select id="sumUserPointByColumnIdWithPointType" resultType="java.lang.Double">
         SELECT COALESCE(SUM(d.point), 0)
         FROM work_knowledge_base_point_detail d
         LEFT JOIN work_knowledge_point_category c ON c.id = d.category_id AND c.del_flag = '0'
@@ -792,7 +792,7 @@
             IFNULL(d.share_id, '')    AS "shareId",
             d.category_id AS "categoryId",
             d.rule_id     AS "ruleId",
-            CAST(IFNULL(d.point, 0) AS SIGNED) AS "point",
+            IFNULL(d.point, 0) AS "point",
             d.create_date AS "createDate",
             IFNULL(s.name, '')          AS "shareName",
             IFNULL(s.tree_node_id, '')  AS "treeNodeId",

+ 2 - 2
src/main/resources/mysqlDateBase/init_work_knowledge_base_point_rule_data.sql

@@ -64,7 +64,7 @@ INSERT INTO work_knowledge_base_point_rule (
     create_date, update_date
 ) VALUES (
     REPLACE(UUID(), '-', ''), @basic_category_id, CONCAT('0,', @basic_category_id, ','), 2, 2, 1,
-    '阅读知识库内容', 3, 1, 1, 1, '0',
+    '阅读知识库内容', 3, 1, 0.5, 1, '0',
     NOW(), NOW()
 );
 
@@ -75,7 +75,7 @@ INSERT INTO work_knowledge_base_point_rule (
     create_date, update_date
 ) VALUES (
     REPLACE(UUID(), '-', ''), @basic_category_id, CONCAT('0,', @basic_category_id, ','), 2, 2, 2,
-    '点赞他人上传内容', 3, 1, 1, 1, '0',
+    '点赞他人上传内容', 3, 1, 0.5, 1, '0',
     NOW(), NOW()
 );
 

+ 66 - 0
src/main/resources/mysqlDateBase/upgrade_read_like_half_point.sql

@@ -0,0 +1,66 @@
+-- =====================================================================
+-- 阅读/点赞积分调整为 0.5 分 —— 生产库升级脚本(唯一需要执行的 SQL)
+-- 日期:2026-10-21
+-- 特性:幂等,可重复执行,执行顺序无依赖
+-- 说明:
+--   1. 本脚本覆盖存量库的全部升级内容(规则值 + 表精度);
+--   2. wk_point_snapshot_tables.sql / init_work_knowledge_base_point_rule_data.sql
+--      为全新环境安装脚本,已同步为 0.5 和 DECIMAL,存量库无需执行;
+--   3. 违规处理记录表(work_knowledge_base_violation_record)不需要升级:
+--      原积分=创建积分之和(整数)、扣除积分=四舍五入取整,INT 列可继续使用。
+-- =====================================================================
+
+-- ---------------------------------------------------------------------
+-- 一、规则值调整:阅读、点赞 每次 1 分 -> 0.5 分
+-- ---------------------------------------------------------------------
+
+-- 0. point_value 列 INT -> VARCHAR(20)(必须先改,否则 INT 列存 0.5 会被四舍五入回 1)
+--    实体字段为 String,VARCHAR 同时容纳整数"20"和小数"0.5";
+--    注意不能改成 DECIMAL:DECIMAL 读出来是"20.00",
+--    贡献积分链路的 Integer.parseInt 会直接报 NumberFormatException。
+ALTER TABLE work_knowledge_base_point_rule
+    MODIFY COLUMN `point_value` VARCHAR(20) DEFAULT NULL COMMENT '积分值';
+
+-- 1. 更新阅读/点赞规则值为 0.5(如已改过,重复执行无副作用)
+UPDATE work_knowledge_base_point_rule
+SET point_value = '0.5',
+    update_date = NOW()
+WHERE node_type = 2
+  AND del_flag = '0'
+  AND point_name IN ('阅读', '点赞');
+
+-- ---------------------------------------------------------------------
+-- 二、表精度升级:所有会存到 0.5 小数的积分列 INT -> DECIMAL(10,2)
+--     (否则写入小数时 MySQL 严格模式报错、非严格模式四舍五入失真)
+-- ---------------------------------------------------------------------
+
+-- 1. 积分明细表(账本,每笔实际发放的分数;如已升级过,重复执行无副作用)
+ALTER TABLE work_knowledge_base_point_detail
+    MODIFY COLUMN `point` DECIMAL(10,2) DEFAULT 0 COMMENT '积分值';
+
+-- 2. 快照明细表(钻取查询用,保存每条积分明细的快照)
+ALTER TABLE wk_point_snapshot_detail
+    MODIFY COLUMN `point` DECIMAL(10,2) DEFAULT 0 COMMENT '积分值';
+
+-- 3. 快照汇总表(公司/部门/员工三级)
+ALTER TABLE wk_point_snapshot_summary
+    MODIFY COLUMN `basic_subtotal`    DECIMAL(10,2) DEFAULT 0 COMMENT '基础积分汇总',
+    MODIFY COLUMN `basic_exchange`    DECIMAL(10,2) DEFAULT 0 COMMENT '基础已兑换积分',
+    MODIFY COLUMN `basic_remaining`   DECIMAL(10,2) DEFAULT 0 COMMENT '基础剩余积分',
+    MODIFY COLUMN `contrib_subtotal`  DECIMAL(10,2) DEFAULT 0 COMMENT '贡献积分汇总(含扣除)',
+    MODIFY COLUMN `contrib_deduction` DECIMAL(10,2) DEFAULT 0 COMMENT '贡献-扣除积分',
+    MODIFY COLUMN `contrib_exchange`  DECIMAL(10,2) DEFAULT 0 COMMENT '贡献已兑换积分',
+    MODIFY COLUMN `contrib_remaining` DECIMAL(10,2) DEFAULT 0 COMMENT '贡献剩余积分';
+
+-- ---------------------------------------------------------------------
+-- 三、执行后验证(可选)
+-- ---------------------------------------------------------------------
+-- 规则值应为 0.5(列类型应为 varchar):
+-- SELECT point_name, point_value FROM work_knowledge_base_point_rule
+--  WHERE point_name IN ('阅读知识库内容', '点赞他人上传内容');
+-- 列类型应为 decimal(10,2):
+-- SELECT TABLE_NAME, COLUMN_NAME, COLUMN_TYPE FROM information_schema.COLUMNS
+--  WHERE TABLE_SCHEMA = DATABASE()
+--    AND ((TABLE_NAME = 'work_knowledge_base_point_detail' AND COLUMN_NAME = 'point')
+--      OR (TABLE_NAME = 'wk_point_snapshot_detail' AND COLUMN_NAME = 'point')
+--      OR (TABLE_NAME = 'wk_point_snapshot_summary' AND COLUMN_NAME LIKE '%subtotal%'));

+ 8 - 8
src/main/resources/mysqlDateBase/wk_point_snapshot_tables.sql

@@ -63,13 +63,13 @@ CREATE TABLE IF NOT EXISTS `wk_point_snapshot_summary` (
     `user_id` VARCHAR(64) DEFAULT NULL COMMENT '用户ID(员工级才有)',
     `user_name` VARCHAR(100) DEFAULT NULL COMMENT '用户姓名',
     `upload_count` INT DEFAULT 0 COMMENT '上传文档数',
-    `basic_subtotal` INT DEFAULT 0 COMMENT '基础积分汇总',
-    `basic_exchange` INT DEFAULT 0 COMMENT '基础已兑换积分',
-    `basic_remaining` INT DEFAULT 0 COMMENT '基础剩余积分',
-    `contrib_subtotal` INT DEFAULT 0 COMMENT '贡献积分汇总(含扣除)',
-    `contrib_deduction` INT DEFAULT 0 COMMENT '贡献-扣除积分',
-    `contrib_exchange` INT DEFAULT 0 COMMENT '贡献已兑换积分',
-    `contrib_remaining` INT DEFAULT 0 COMMENT '贡献剩余积分',
+    `basic_subtotal` DECIMAL(10,2) DEFAULT 0 COMMENT '基础积分汇总',
+    `basic_exchange` DECIMAL(10,2) DEFAULT 0 COMMENT '基础已兑换积分',
+    `basic_remaining` DECIMAL(10,2) DEFAULT 0 COMMENT '基础剩余积分',
+    `contrib_subtotal` DECIMAL(10,2) DEFAULT 0 COMMENT '贡献积分汇总(含扣除)',
+    `contrib_deduction` DECIMAL(10,2) DEFAULT 0 COMMENT '贡献-扣除积分',
+    `contrib_exchange` DECIMAL(10,2) DEFAULT 0 COMMENT '贡献已兑换积分',
+    `contrib_remaining` DECIMAL(10,2) DEFAULT 0 COMMENT '贡献剩余积分',
     PRIMARY KEY (`id`),
     KEY `idx_summary_ym_grade` (`snapshot_year`, `snapshot_month`, `grade_type`),
     KEY `idx_summary_office` (`office_id`, `snapshot_year`, `snapshot_month`)
@@ -94,7 +94,7 @@ CREATE TABLE IF NOT EXISTS `wk_point_snapshot_detail` (
     `category_name` VARCHAR(200) DEFAULT '' COMMENT '分类名称',
     `rule_id` VARCHAR(64) DEFAULT '' COMMENT '规则ID',
     `rule_type` INT DEFAULT 0 COMMENT '规则类型(1=创建,2=审核,10=阅读,20=点赞)',
-    `point` INT DEFAULT 0 COMMENT '积分值',
+    `point` DECIMAL(10,2) DEFAULT 0 COMMENT '积分值',
     `point_create_date` DATETIME DEFAULT NULL COMMENT '积分产生时间',
     PRIMARY KEY (`id`),
     KEY `idx_snap_detail_ym` (`snapshot_year`, `snapshot_month`),

+ 1 - 1
src/main/webapp/webpage/modules/WorkKnowledgeBase/workKnowledgeBasePointDrillDown.jsp

@@ -228,7 +228,7 @@
                     return '-';
                 }}
                 ,{field:'point',align:'center', title: '积分额度', width:100,templet:function(d){
-                    var val = d.point || 0;
+                    var val = parseFloat(d.point) || 0;
                     var prefix = val >= 0 ? '+' : '';
                     var color = val >= 0 ? '#1aa094' : '#ff5722';
                     return '<span style="color:' + color + ';font-weight:bold;">' + prefix + val + '</span>';

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

@@ -49,9 +49,9 @@
             {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:'originalBasicPoint', align:'center', title:'当前基础积分', width:120, templet:function(d){ return '<span style="color:#1aa094;font-weight:bold;">' + (parseFloat(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},
+            {field:'remainingBasicPoint', align:'center', title:'兑换后剩余', width:110, templet:function(d){ return parseFloat(d.remainingBasicPoint) || 0; }},
             {field:'exchangeAmount', align:'center', title:'兑换金额(元)', width:120, templet:function(d){ return '<span style="color:#FF5722;font-weight:bold;">' + (d.exchangeAmount || 0) + ' 元</span>'; }}
         ]];
     } else {

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

@@ -229,10 +229,10 @@
                     return d.mobile || d.phone || '';
                 }}
                 ,{field:'totalPoint', align: 'center', title: '积分数量', width: 110, templet: function(d) {
-                    return '<span style="color:#1aa094;font-weight:bold;">' + (d.totalPoint || 0) + '</span>';
+                    return '<span style="color:#1aa094;font-weight:bold;">' + (parseFloat(d.totalPoint) || 0) + '</span>';
                 }}
 				,{field:'monthlyPoint', align: 'center', title: '当月积分数量', width: 110, templet: function(d) {
-                    return '<span style="color:#1aa094;font-weight:bold;">' + parseInt(d.monthlyPoint || 0) + '</span>';
+                    return '<span style="color:#1aa094;font-weight:bold;">' + (parseFloat(d.monthlyPoint) || 0) + '</span>';
                 }}
             ]]
             ,data: [

+ 5 - 5
src/main/webapp/webpage/modules/WorkKnowledgeBase/workKnowledgeBasePointRanking.jsp

@@ -163,9 +163,9 @@
                 ,{field:'officeName', align: 'center', title: '所属部门', minWidth: 160}
                 ,{field:'mobile', align: 'center', title: '手机号', minWidth: 130, templet: function(d) { return d.mobile || d.phone || ''; }}
                 ,{field:'exchangedBasicPoint', align: 'center', title: '基础已兑换', width: 110}
-                ,{field:'remainingBasicPoint', align: 'center', title: '基础剩余', width: 100}
+                ,{field:'remainingBasicPoint', align: 'center', title: '基础剩余', width: 100, templet: function(d) { return parseFloat(d.remainingBasicPoint) || 0; }}
                 ,{field:'basicPoint', align: 'center', title: '基础积分(总获取)', width: 130, templet: function(d) {
-                    return '<span style="color:#2e7d32;font-weight:bold;">' + (d.basicPoint || 0) + '</span>';
+                    return '<span style="color:#2e7d32;font-weight:bold;">' + (parseFloat(d.basicPoint) || 0) + '</span>';
                 }}
             ]];
         } else {
@@ -178,17 +178,17 @@
                 ,{field:'officeName', align: 'center', title: '所属部门', minWidth: 160}
                 ,{field:'mobile', align: 'center', title: '手机号', minWidth: 130, templet: function(d) { return d.mobile || d.phone || ''; }}
                 ,{field:'basicPoint', align: 'center', title: '基础积分(总获取)', width: 120, templet: function(d) {
-                    return '<span style="color:#2e7d32;font-weight:bold;">' + (d.basicPoint || 0) + '</span>';
+                    return '<span style="color:#2e7d32;font-weight:bold;">' + (parseFloat(d.basicPoint) || 0) + '</span>';
                 }}
                 ,{field:'exchangedBasicPoint', align: 'center', title: '基础已兑换', width: 100}
-                ,{field:'remainingBasicPoint', align: 'center', title: '基础剩余', width: 90}
+                ,{field:'remainingBasicPoint', align: 'center', title: '基础剩余', width: 90, templet: function(d) { return parseFloat(d.remainingBasicPoint) || 0; }}
                 ,{field:'contributionPoint', align: 'center', title: '贡献积分(总获取)', width: 130, templet: function(d) {
                     return '<span style="color:#1565c0;font-weight:bold;">' + (d.contributionPoint || 0) + '</span>';
                 }}
                 ,{field:'exchangedContributionPoint', align: 'center', title: '贡献已兑换', width: 110}
                 ,{field:'remainingContributionPoint', align: 'center', title: '贡献剩余', width: 100}
                 ,{field:'totalPoint', align: 'center', title: '总积分', width: 100, templet: function(d) {
-                    return '<span style="color:#1aa094;font-weight:bold;font-size:15px;">' + (d.totalPoint || 0) + '</span>';
+                    return '<span style="color:#1aa094;font-weight:bold;font-size:15px;">' + (parseFloat(d.totalPoint) || 0) + '</span>';
                 }}
             ]];
         }

+ 2 - 2
src/main/webapp/webpage/modules/WorkKnowledgeBase/workKnowledgeBasePointUserDetail.jsp

@@ -143,7 +143,7 @@
 					return d.categoryName || '-';
 				}}
 				,{field:'ruleType',align:'center', title: '获取方式', width:110,templet:function(d){
-					var val = parseInt(d.point) || 0;
+					var val = parseFloat(d.point) || 0;
 					// 先判断是否为扣分标准分类(违规扣分)
 					if (d.categoryName && d.categoryName.indexOf('扣分标准') !== -1) {
 						return '<span class="layui-badge layui-bg-black">扣分</span>';
@@ -157,7 +157,7 @@
 					return '-';
 				}}
 				,{field:'point',align:'center', title: '积分额度', width:100,templet:function(d){
-					var val = d.point || 0;
+					var val = parseFloat(d.point) || 0;
 					var prefix = val >= 0 ? '+' : '';
 					var color = val >= 0 ? '#1aa094' : '#ff5722';
 					return '<span style="color:' + color + ';font-weight:bold;">' + prefix + val + '</span>';

+ 1 - 1
src/main/webapp/webpage/modules/WorkKnowledgeBase/workKnowledgeBasePointUserList.jsp

@@ -116,7 +116,7 @@
                     return d.mobile || d.phone || '';
                 }}
                 ,{field:'totalPoint', align: 'center', title: '积分数量', width: 110, templet: function(d) {
-                    return '<span style="color:#1aa094;font-weight:bold;">' + (d.totalPoint || 0) + '</span>';
+                    return '<span style="color:#1aa094;font-weight:bold;">' + (parseFloat(d.totalPoint) || 0) + '</span>';
                 }}
             ]]
             ,data: [

+ 22 - 3
src/main/webapp/webpage/modules/WorkKnowledgeBase/workKnowledgeBaseShareDetail.jsp

@@ -102,6 +102,25 @@
             }
         });
         
+        // 时间格式化:秒 -> "X秒" / "X分Y秒" / "X时Y分Z秒"
+        function formatDuration(seconds) {
+            if (seconds < 60) {
+                return seconds + '秒';
+            } else if (seconds < 3600) {
+                var minutes = Math.floor(seconds / 60);
+                var secs = seconds % 60;
+                return secs === 0 ? minutes + '分钟' : minutes + '分' + secs + '秒';
+            } else {
+                var hours = Math.floor(seconds / 3600);
+                var minutes = Math.floor((seconds % 3600) / 60);
+                var secs = seconds % 60;
+                var result = hours + '小时';
+                if (minutes > 0) result += minutes + '分';
+                if (secs > 0) result += secs + '秒';
+                return result;
+            }
+        }
+        
         function doSubmit(obj){
             console.log('doSubmit called, obj=', obj);
             if (!canAuditFlag) {
@@ -130,13 +149,13 @@
                 
                 if (obj == 1) {
                     // ========== 前端校验:停留时长和附件查看(仅“通过”操作) ==========
-                    var minStaySeconds = ${minStaySeconds != null ? minStaySeconds : 30};
+                    var minStaySeconds = ${minStaySeconds != null ? minStaySeconds : 180};
                     if (isViewedAttachment != 1) {
-                        parent.layer.msg('您还没有查看附件信息,请认真查看附件内容至少' + minStaySeconds + '秒后再审核', {icon: 5, time: 5000});
+                        parent.layer.msg('您还没有查看附件信息,请认真查看附件内容至少' + formatDuration(minStaySeconds) + '后再审核', {icon: 5, time: 5000});
                         return false;
                     }
                     if (viewDurationSeconds < minStaySeconds) {
-                        parent.layer.msg('您查看附件仅' + viewDurationSeconds + '秒,低于最低要求' + minStaySeconds + '秒,请认真查看附件内容后再审核', {icon: 5, time: 5000});
+                        parent.layer.msg('您查看附件仅' + formatDuration(viewDurationSeconds) + ',低于最低要求' + formatDuration(minStaySeconds) + ',请认真查看附件内容后再审核', {icon: 5, time: 5000});
                         return false;
                     }