Bläddra i källkod

需求代码提交

yuhongqi 1 månad sedan
förälder
incheckning
9a4609bf72

+ 145 - 1
fs-service-system/src/main/java/com/fs/live/service/impl/LiveMsgServiceImpl.java

@@ -1,16 +1,23 @@
 package com.fs.live.service.impl;
 
 
+import com.alibaba.fastjson.JSON;
+import com.fs.common.core.redis.RedisUtil;
 import com.fs.common.utils.DateUtils;
 import com.fs.live.domain.LiveMsg;
 import com.fs.live.mapper.LiveMsgMapper;
 import com.fs.live.service.ILiveMsgService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.core.script.DefaultRedisScript;
 import org.springframework.stereotype.Service;
 
 import java.util.Collections;
 import java.util.Date;
 import java.util.List;
+import java.util.concurrent.TimeUnit;
 
 /**
  * 直播讨论Service业务层处理
@@ -21,10 +28,29 @@ import java.util.List;
 @Service
 public class LiveMsgServiceImpl implements ILiveMsgService
 {
+    private static final Logger log = LoggerFactory.getLogger(LiveMsgServiceImpl.class);
+    
     @Autowired
     private LiveMsgMapper liveMsgMapper;
     @Autowired
     private LiveDataServiceImpl liveDataService;
+    @Autowired
+    private RedisUtil redisUtil;
+    @Autowired
+    private RedisTemplate<String, Object> redisTemplate;
+    
+    /** 直播间消息缓存key前缀 */
+    private static final String LIVE_MSG_CACHE_KEY_PREFIX = "live:msg:list:";
+    /** 直播间消息更新时间key前缀 */
+    private static final String LIVE_MSG_UPDATE_TIME_KEY_PREFIX = "live:msg:update:time:";
+    /** 锁key前缀 */
+    private static final String LIVE_MSG_LOCK_KEY_PREFIX = "live:msg:lock:";
+    /** 消息更新时间阈值(秒) */
+    private static final long UPDATE_TIME_THRESHOLD = 5;
+    /** 消息缓存过期时间(小时) */
+    private static final long MSG_CACHE_EXPIRE_HOURS = 24;
+    /** 更新时间缓存过期时间(秒) */
+    private static final long UPDATE_TIME_CACHE_EXPIRE_SECONDS = 5;
 
     /**
      * 查询直播讨论
@@ -47,7 +73,125 @@ public class LiveMsgServiceImpl implements ILiveMsgService
     @Override
     public List<LiveMsg> selectLiveMsgList(LiveMsg liveMsg)
     {
-        return liveMsgMapper.selectLiveMsgList(liveMsg);
+        // 如果liveId为空,直接查询数据库
+        if (liveMsg == null || liveMsg.getLiveId() == null) {
+            return liveMsgMapper.selectLiveMsgList(liveMsg);
+        }
+        
+        Long liveId = liveMsg.getLiveId();
+        String cacheKey = LIVE_MSG_CACHE_KEY_PREFIX + liveId;
+        String updateTimeKey = LIVE_MSG_UPDATE_TIME_KEY_PREFIX + liveId;
+        String lockKey = LIVE_MSG_LOCK_KEY_PREFIX + liveId;
+        
+        try {
+            // 1. 先查redis消息时间
+            String updateTimeStr = redisUtil.getString(updateTimeKey);
+            long currentTime = System.currentTimeMillis();
+            boolean needUpdate = false;
+            
+            if (updateTimeStr == null || updateTimeStr.isEmpty()) {
+                // 如果更新时间不存在,需要更新
+                needUpdate = true;
+            } else {
+                try {
+                    long lastUpdateTime = Long.parseLong(updateTimeStr);
+                    long timeDiff = (currentTime - lastUpdateTime) / 1000; // 转换为秒
+                    if (timeDiff >= UPDATE_TIME_THRESHOLD) {
+                        // 如果时间超过了5s,需要更新
+                        needUpdate = true;
+                    }
+                } catch (NumberFormatException e) {
+                    log.warn("解析更新时间失败,liveId: {}, updateTimeStr: {}", liveId, updateTimeStr);
+                    needUpdate = true;
+                }
+            }
+            
+            // 2. 如果时间超过了5s,那么就拿锁进行更新
+            if (needUpdate) {
+                // 使用Redis SETNX实现分布式锁
+                boolean lockAcquired = tryLock(lockKey, 10);
+                if (lockAcquired) {
+                    try {
+                        // 3. 更新缓存中的直播间消息,设置过期时间24小时
+                        List<LiveMsg> msgList = liveMsgMapper.selectLiveMsgList(liveMsg);
+                        if (msgList != null) {
+                            String msgListJson = JSON.toJSONString(msgList);
+                            redisUtil.setString(cacheKey, msgListJson, MSG_CACHE_EXPIRE_HOURS, TimeUnit.HOURS);
+                        }
+                        
+                        // 4. 设置redis消息时间为5s后
+                        long nextUpdateTime = currentTime + (UPDATE_TIME_CACHE_EXPIRE_SECONDS * 1000);
+                        redisUtil.setString(updateTimeKey, String.valueOf(nextUpdateTime), 
+                                UPDATE_TIME_CACHE_EXPIRE_SECONDS, TimeUnit.SECONDS);
+                        
+                        return msgList != null ? msgList : Collections.emptyList();
+                    } finally {
+                        releaseLock(lockKey);
+                    }
+                } else {
+                    // 5. 如果没拿到锁,直接返回缓存中的直播间消息
+                    return getCachedMsgList(cacheKey);
+                }
+            } else {
+                // 时间未超过5s,直接返回缓存
+                return getCachedMsgList(cacheKey);
+            }
+        } catch (Exception e) {
+            log.error("查询直播间消息列表异常,liveId: {}", liveId, e);
+            // 异常情况下,直接查询数据库
+            return liveMsgMapper.selectLiveMsgList(liveMsg);
+        }
+    }
+    
+    /**
+     * 从缓存获取消息列表
+     */
+    private List<LiveMsg> getCachedMsgList(String cacheKey) {
+        try {
+            String msgListJson = redisUtil.getString(cacheKey);
+            if (msgListJson != null && !msgListJson.isEmpty()) {
+                List<LiveMsg> msgList = JSON.parseArray(msgListJson, LiveMsg.class);
+                return msgList != null ? msgList : Collections.emptyList();
+            }
+        } catch (Exception e) {
+            log.warn("从缓存获取消息列表失败,cacheKey: {}", cacheKey, e);
+        }
+        return Collections.emptyList();
+    }
+    
+    /**
+     * 尝试获取分布式锁(使用SETNX)
+     * @param lockKey 锁的key
+     * @param expireSeconds 锁的过期时间(秒)
+     * @return 是否获取成功
+     */
+    private boolean tryLock(String lockKey, long expireSeconds) {
+        try {
+            Boolean result = redisTemplate.opsForValue().setIfAbsent(lockKey, "1", expireSeconds, TimeUnit.SECONDS);
+            return Boolean.TRUE.equals(result);
+        } catch (Exception e) {
+            log.error("获取锁失败,lockKey: {}", lockKey, e);
+            return false;
+        }
+    }
+    
+    /**
+     * 释放分布式锁
+     * @param lockKey 锁的key
+     */
+    private void releaseLock(String lockKey) {
+        try {
+            // 使用Lua脚本确保只删除自己设置的锁
+            String luaScript = "if redis.call('get', KEYS[1]) == ARGV[1] then " +
+                    "return redis.call('del', KEYS[1]) " +
+                    "else return 0 end";
+            DefaultRedisScript<Long> script = new DefaultRedisScript<>();
+            script.setScriptText(luaScript);
+            script.setResultType(Long.class);
+            redisTemplate.execute(script, Collections.singletonList(lockKey), "1");
+        } catch (Exception e) {
+            log.error("释放锁失败,lockKey: {}", lockKey, e);
+        }
     }
 
     /**

+ 8 - 0
fs-service-system/src/main/java/com/fs/store/domain/FsStoreProduct.java

@@ -186,4 +186,12 @@ public class FsStoreProduct extends BaseEntity
 
     private String erp;
 
+    /** 税收分类码 */
+    @Excel(name = "税收分类码")
+    private String taxClassificationCode;
+
+    /** 商品发票名称 */
+    @Excel(name = "商品发票名称")
+    private String invoiceName;
+
 }

+ 15 - 0
fs-service-system/src/main/java/com/fs/store/domain/FsStoreProductAttrValue.java

@@ -86,6 +86,10 @@ public class FsStoreProductAttrValue extends BaseEntity
 
     private BigDecimal agentPrice;
 
+    /** 税率 */
+    @Excel(name = "税率")
+    private BigDecimal taxRate;
+
     private Map<String, String> detail;
 
     public BigDecimal getBrokerageThree() {
@@ -256,6 +260,16 @@ public class FsStoreProductAttrValue extends BaseEntity
         return integral;
     }
 
+    public void setTaxRate(BigDecimal taxRate)
+    {
+        this.taxRate = taxRate;
+    }
+
+    public BigDecimal getTaxRate()
+    {
+        return taxRate;
+    }
+
     @Override
     public String toString() {
         return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
@@ -274,6 +288,7 @@ public class FsStoreProductAttrValue extends BaseEntity
             .append("brokerage", getBrokerage())
             .append("brokerageTwo", getBrokerageTwo())
             .append("integral", getIntegral())
+            .append("taxRate", getTaxRate())
             .toString();
     }
 }

+ 6 - 0
fs-service-system/src/main/java/com/fs/store/param/FsStoreProductAddEditParam.java

@@ -151,6 +151,12 @@ public class FsStoreProductAddEditParam implements Serializable
     //sku结果集
     private List<FsStoreProductAttrValue> values;
 
+    /** 税收分类码 */
+    @Excel(name = "税收分类码")
+    private String taxClassificationCode;
 
+    /** 商品发票名称 */
+    @Excel(name = "商品发票名称")
+    private String invoiceName;
 
 }

+ 1 - 0
fs-service-system/src/main/java/com/fs/store/service/impl/FsStoreProductServiceImpl.java

@@ -515,6 +515,7 @@ public class FsStoreProductServiceImpl implements IFsStoreProductService
                     valueMap.put("brokerageTwo", values.get(0).getBrokerageTwo());
                     valueMap.put("brokerageThree", values.get(0).getBrokerageThree());
                     valueMap.put("integral", values.get(0).getIntegral());
+                    valueMap.put("taxRate", values.get(0).getTaxRate());
                 }
             }
             valueMapList.add(ObjectUtil.clone(valueMap));

+ 6 - 1
fs-service-system/src/main/resources/mapper/store/FsStoreProductAttrValueMapper.xml

@@ -23,10 +23,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <result property="brokerageTwo"    column="brokerage_two"    />
         <result property="brokerageThree"    column="brokerage_three"    />
         <result property="integral"    column="integral"    />
+        <result property="taxRate"    column="tax_rate"    />
     </resultMap>
 
     <sql id="selectFsStoreProductAttrValueVo">
-        select id, product_id, sku, stock, sales, price, image, cost,agent_price, bar_code,group_bar_code, ot_price, weight, volume, brokerage, brokerage_two,brokerage_three, integral from fs_store_product_attr_value
+        select id, product_id, sku, stock, sales, price, image, cost,agent_price, bar_code,group_bar_code, ot_price, weight, volume, brokerage, brokerage_two,brokerage_three, integral, tax_rate from fs_store_product_attr_value
     </sql>
 
     <select id="selectFsStoreProductAttrValueList" parameterType="FsStoreProductAttrValue" resultMap="FsStoreProductAttrValueResult">
@@ -48,6 +49,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="brokerageTwo != null "> and brokerage_two = #{brokerageTwo}</if>
             <if test="brokerageThree != null "> and brokerage_three = #{brokerageThree}</if>
             <if test="integral != null "> and integral = #{integral}</if>
+            <if test="taxRate != null "> and tax_rate = #{taxRate}</if>
         </where>
     </select>
 
@@ -76,6 +78,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="brokerageTwo != null">brokerage_two,</if>
             <if test="brokerageThree != null">brokerage_three,</if>
             <if test="integral != null">integral,</if>
+            <if test="taxRate != null">tax_rate,</if>
          </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="productId != null">#{productId},</if>
@@ -95,6 +98,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="brokerageTwo != null">#{brokerageTwo},</if>
             <if test="brokerageThree != null">#{brokerageThree},</if>
             <if test="integral != null">#{integral},</if>
+            <if test="taxRate != null">#{taxRate},</if>
          </trim>
     </insert>
 
@@ -118,6 +122,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="brokerageTwo != null">brokerage_two = #{brokerageTwo},</if>
             <if test="brokerageThree != null">brokerage_three = #{brokerageThree},</if>
             <if test="integral != null">integral = #{integral},</if>
+            <if test="taxRate != null">tax_rate = #{taxRate},</if>
         </trim>
         where id = #{id}
     </update>

+ 11 - 1
fs-service-system/src/main/resources/mapper/store/FsStoreProductMapper.xml

@@ -47,10 +47,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <result property="prescribeName"    column="prescribe_name"    />
         <result property="isDisplay"    column="is_display"    />
         <result property="tuiCateId"    column="tui_cate_id"    />
+        <result property="taxClassificationCode"    column="tax_classification_code"    />
+        <result property="invoiceName"    column="invoice_name"    />
     </resultMap>
 
     <sql id="selectFsStoreProductVo">
-        select product_id, image, slider_image, product_name, product_info, keyword, bar_code, cate_id, price, vip_price, ot_price, postage, unit_name, sort, sales, stock, is_show, is_hot, is_benefit, is_best, is_new, description, create_time, update_time, is_postage, is_del, give_integral, cost, is_good, browse, code_path, temp_id, spec_type, is_integral, integral, product_type, prescribe_code, prescribe_spec, prescribe_factory, prescribe_name,is_display,tui_cate_id,warehouse_id,warehouse_code from fs_store_product
+        select product_id, image, slider_image, product_name, product_info, keyword, bar_code, cate_id, price, vip_price, ot_price, postage, unit_name, sort, sales, stock, is_show, is_hot, is_benefit, is_best, is_new, description, create_time, update_time, is_postage, is_del, give_integral, cost, is_good, browse, code_path, temp_id, spec_type, is_integral, integral, product_type, prescribe_code, prescribe_spec, prescribe_factory, prescribe_name,is_display,tui_cate_id,warehouse_id,warehouse_code,tax_classification_code,invoice_name from fs_store_product
     </sql>
 
     <select id="selectFsStoreProductList" parameterType="FsStoreProduct" resultMap="FsStoreProductResult">
@@ -96,6 +98,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="isDisplay != null "> and is_display = #{isDisplay}</if>
             <if test="warehouseId != null"> and warehouse_id = #{warehouseId}</if>
             <if test="warehouseCode != null"> and warehouse_code = #{warehouseCode}</if>
+            <if test="taxClassificationCode != null  and taxClassificationCode != ''"> and tax_classification_code = #{taxClassificationCode}</if>
+            <if test="invoiceName != null  and invoiceName != ''"> and invoice_name like concat('%', #{invoiceName}, '%')</if>
         </where>
     </select>
 
@@ -150,6 +154,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="tuiCateId != null">tui_cate_id,</if>
             <if test="warehouseId != null">warehouse_id,</if>
             <if test="warehouseCode != null">warehouse_code,</if>
+            <if test="taxClassificationCode != null and taxClassificationCode != ''">tax_classification_code,</if>
+            <if test="invoiceName != null and invoiceName != ''">invoice_name,</if>
          </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="image != null and image != ''">#{image},</if>
@@ -195,6 +201,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="tuiCateId != null">#{tuiCateId},</if>
             <if test="warehouseId != null">#{warehouseId},</if>
             <if test="warehouseCode != null">#{warehouseCode},</if>
+            <if test="taxClassificationCode != null and taxClassificationCode != ''">#{taxClassificationCode},</if>
+            <if test="invoiceName != null and invoiceName != ''">#{invoiceName},</if>
          </trim>
     </insert>
 
@@ -244,6 +252,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="tuiCateId != null">tui_cate_id = #{tuiCateId},</if>
             <if test="warehouseId != null">warehouse_id = #{warehouseId},</if>
             <if test="warehouseCode != null">warehouse_code = #{warehouseCode},</if>
+            <if test="taxClassificationCode != null and taxClassificationCode != ''">tax_classification_code = #{taxClassificationCode},</if>
+            <if test="invoiceName != null and invoiceName != ''">invoice_name = #{invoiceName},</if>
         </trim>
         where product_id = #{productId}
     </update>