1
0
Quellcode durchsuchen

增加幸运抽奖活动运营服务能力

wangqi49 vor 5 Monaten
Ursprung
Commit
8ffc79c0f2

+ 2 - 1
sql/webchat.sql

@@ -250,6 +250,7 @@ CREATE TABLE webchat.web_chat_article (
       `TITLE` varchar(100) NOT NULL COMMENT '文章标题',
       `CONTENT` longtext NOT NULL COMMENT '正文',
       `COVER` varchar(400) NOT NULL COMMENT '封面图',
+      `REDIRECT_URL` varchar(400) DEFAULT NULL COMMENT '外部连接',
       `DESCRIPTION` varchar(200) DEFAULT NULL COMMENT '摘要/智能总结',
       `signs` varchar(200) DEFAULT NULL COMMENT '标签',
       `PLAN_PUSH_DATE` datetime DEFAULT NULL  COMMENT '计划推文时间',
@@ -296,7 +297,7 @@ CREATE TABLE webchat.`web_chat_lottery_activity` (
        `ACTIVITY_ID` char(100) NOT NULL COMMENT '抽奖活动业务ID',
        `NAME` varchar(100) NOT NULL COMMENT '活动名称',
        `DESCRIPTION` varchar(500) NOT NULL COMMENT '活动描述',
-       `INTEGRAL` int(11) NOT NULL DEFAULT 0 COMMENT '每次抽奖需要消耗的元气值个数',
+       `INTEGRAL` int(11) NOT NULL DEFAULT 0 COMMENT '每次抽奖需要消耗的金币个数',
        `COVER` varchar(300) NOT NULL COMMENT '活动封面图',
        `STATUS` int(11) NOT NULL COMMENT '活动状态',
        `CREATE_BY` char(100) DEFAULT NULL COMMENT '创建人',

+ 9 - 0
src/main/java/com/webchat/controller/PageController.java

@@ -29,6 +29,15 @@ public class PageController {
         return "client/auth";
     }
 
+    /**
+     * 抽奖页面路由
+     * @return
+     */
+    @GetMapping("/luck")
+    public String luck() {
+        return "client/luck";
+    }
+
     /***
      * 聊天室鉴权路由
      * @return

+ 1 - 1
src/main/java/com/webchat/controller/client/GroupVideoChatDcsWebSocket.java

@@ -29,7 +29,7 @@ import java.util.concurrent.ConcurrentHashMap;
 @Data
 @Slf4j
 @Component
-@ServerEndpoint(value = "/ws/group-video-chat/{groupId}/{userId}")
+@ServerEndpoint(value = "/ws/group-video-chat/dcs/{groupId}/{userId}")
 public class GroupVideoChatDcsWebSocket {
     /**
      * 群聊多人音视频webscoket连接对象存储

+ 5 - 0
src/main/java/com/webchat/domain/vo/request/publicaccount/SaveArticleRequestVO.java

@@ -55,6 +55,11 @@ public class SaveArticleRequestVO {
     private String signs;
 
     /**
+     * 文章跳转链接(配置了该链接,默认跳转到链接指向地址,扩展公众号推送能力)
+     */
+    private String redirectUrl;
+
+    /**
      * 文章状态
      *
      * @see com.webchat.common.enums.ArticleStatusEnum

+ 1 - 1
src/main/java/com/webchat/domain/vo/response/lottery/LotteryActivityBaseVO.java

@@ -29,7 +29,7 @@ public class LotteryActivityBaseVO {
     private String description;
 
     /**
-     * 每抽奖一次需要消耗的元气值
+     * 每抽奖一次需要消耗的金币
      */
     private Integer integral;
 

+ 2 - 0
src/main/java/com/webchat/domain/vo/response/mess/PublicAccountArticleMessageVO.java

@@ -14,4 +14,6 @@ public class PublicAccountArticleMessageVO {
     private Long time;
 
     private String description;
+
+    private String redirectUrl;
 }

+ 5 - 0
src/main/java/com/webchat/domain/vo/response/publicaccount/ArticleBaseResponseVO.java

@@ -58,6 +58,11 @@ public class ArticleBaseResponseVO {
     private String signs;
 
     /**
+     * 文章跳转链接
+     */
+    private String redirectUrl;
+
+    /**
      * 文章状态
      *
      * @see com.webchat.common.enums.ArticleStatusEnum

+ 6 - 0
src/main/java/com/webchat/repository/entity/ArticleEntity.java

@@ -48,6 +48,12 @@ public class ArticleEntity extends BaseEntity {
     private String cover;
 
     /**
+     * 外部链接地址
+     */
+    @Column(name = "redirect_url")
+    private String redirectUrl;
+
+    /**
      * 文章总结
      */
     @Column(name = "description")

+ 1 - 1
src/main/java/com/webchat/repository/entity/lottery/LotteryActivityEntity.java

@@ -39,7 +39,7 @@ public class LotteryActivityEntity extends BaseEntity {
     private String description;
 
     /**
-     * 每抽奖一次需要消耗的元气值
+     * 每抽奖一次需要消耗的金币
      */
     @Column(name = "integral")
     private Integer integral;

+ 1 - 0
src/main/java/com/webchat/service/lottery/LotteryActivityService.java

@@ -19,6 +19,7 @@ import org.springframework.data.domain.Pageable;
 import org.springframework.data.domain.Sort;
 import org.springframework.data.jpa.domain.Specification;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.Assert;
 
 import javax.persistence.criteria.Predicate;

+ 1 - 0
src/main/java/com/webchat/service/lottery/LotteryCacheService.java

@@ -271,6 +271,7 @@ public class LotteryCacheService {
      * @param itemId
      */
     public void deductItemStock(String lotteryActivityId, Long itemId) {
+        // 这里目前不是原子性操作,在高并发情况下可能会有问题
         RedisKeyEnum lotteryActivityCacheKey = RedisKeyEnum.LOTTERY_ACTIVITY_ITEM_STOCK_CACHE;
         String key = lotteryActivityCacheKey.getKey(lotteryActivityId);
         Map<Long, Integer> stockMap = this.getLotteryItemStockFromCache(lotteryActivityId);

+ 3 - 3
src/main/java/com/webchat/service/lottery/LotteryOrderService.java

@@ -80,7 +80,7 @@ public class LotteryOrderService {
          */
         this.addLotteryUserOrderHistoryCache(lotteryOrder);
         /**
-         * 处理抽到元气值商品的情况
+         * 处理抽到金币商品的情况
          */
         lotteryOrder = this.handleIntegralItemLuckResult(lotteryOrder);
         /**
@@ -95,7 +95,7 @@ public class LotteryOrderService {
      * @param lotteryOrder
      */
     public LotteryOrderEntity handleIntegralItemLuckResult(LotteryOrderEntity lotteryOrder) {
-        log.info("抽奖抽中元气值,消息消费内容:{}", JsonUtil.toJsonString(lotteryOrder));
+        log.info("抽奖抽中金币,消息消费内容:{}", JsonUtil.toJsonString(lotteryOrder));
         String activityId = lotteryOrder.getActivityId();
         Long itemId = lotteryOrder.getItemId();
         String userId = lotteryOrder.getUserId();
@@ -105,7 +105,7 @@ public class LotteryOrderService {
         }
         if (!LotteryConstants.LotteryItemType.INTEGRAL.getType().equals(lotteryItemVO.getType())) {
             // 非猿气值
-            log.info("抽奖未抽中元气值,消息消费内容:{}", JsonUtil.toJsonString(lotteryOrder));
+            log.info("抽奖未抽中金币,消息消费内容:{}", JsonUtil.toJsonString(lotteryOrder));
             return lotteryOrder;
         }
         String name = lotteryItemVO.getName();

+ 4 - 1
src/main/java/com/webchat/service/lottery/LotteryService.java

@@ -71,6 +71,9 @@ public class LotteryService {
      */
     public synchronized List<Long> luckDraw(String lotteryActivityId, String userId, int times) {
         List<Long> result = new Vector<>();
+        /**
+         * 这里下简单实现,这种做法不是很好,并发量大下可能容易出问题
+         */
         for (int i = 0; i < times; i++) {
             Long lotteryItemId = this.doLotteryDraw(lotteryActivityId);
             this.handleLotteryOrder(userId, lotteryActivityId, lotteryItemId);
@@ -169,7 +172,7 @@ public class LotteryService {
      *
      * @param lotteryActivityId
      * @param userId
-     * @return 满足抽奖条件返回抽奖需要消耗的元气值个数
+     * @return 满足抽奖条件返回抽奖需要消耗的金币个数
      */
     private int validateLotteryDrawCondition(String lotteryActivityId, String userId, int times) {
 

+ 2 - 0
src/main/java/com/webchat/service/publicaccount/ArticleService.java

@@ -173,6 +173,7 @@ public class ArticleService {
         publicAccountArticleMessage.setDescription(article.getDescription());
         publicAccountArticleMessage.setCover(article.getCover());
         publicAccountArticleMessage.setArticleId(articleId);
+        publicAccountArticleMessage.setRedirectUrl(article.getRedirectUrl());
         return publicAccountArticleMessage;
     }
 
@@ -292,6 +293,7 @@ public class ArticleService {
             articleEntity.setAuthor(author);
             articleEntity.setStatus(ArticleStatusEnum.WAIT_PUSH.getStatus());
         }
+        articleEntity.setRedirectUrl(saveArticleRequest.getRedirectUrl());
         articleEntity.setStatus(articleEntity.getStatus());
         articleEntity.setCover(saveArticleRequest.getCover());
         articleEntity.setDescription(saveArticleRequest.getDescription());

+ 1 - 1
src/main/resources/application-dev.yml

@@ -7,7 +7,7 @@ server:
     session:
       timeout: 60s
   tomcat:
-    max-threads: 500
+    max-connections: 1000
 
 # set enable swagger
 swagger:

+ 5 - 4
src/main/resources/templates/client/chat.html

@@ -299,7 +299,7 @@
                 message = buildFileMess(JSON.parse(chat.message), me.photo, "right");
             } else if (chat.type === 4) {
                 var article = JSON.parse(chat.message);
-                message = buildPublicAccountMess(article.articleId, article.cover, article.title, article.description);
+                message = buildPublicAccountMess(article.articleId, article.cover, article.title, article.description, article.redirectUrl);
             } else {
                 // 当前用户
                 message =" <p class=\"chat-mess-time\">"+formatMsgTime(chat.time)+"</p>\n" +
@@ -480,7 +480,7 @@
                                 message = buildFileMess(JSON.parse(chat.message), sender.photo, "left");
                             } else if (chat.type === 4) {
                                 var article = chat.publicAccountArticle;
-                                message = buildPublicAccountMess(article.articleId, article.cover, article.title, article.description);
+                                message = buildPublicAccountMess(article.articleId, article.cover, article.title, article.description, article.redirectUrl);
                             } else {
                                 message =" <p class=\"chat-mess-time\">"+formatMsgTime(chat.time)+"</p>\n" +
                                     "                <div class=\"chat-mess-container chat-mess-user\">\n" +
@@ -632,9 +632,10 @@
             "             </div>\n";
     }
 
-    function buildPublicAccountMess(id, img, title, description) {
+    function buildPublicAccountMess(id, img, title, description, redirectUrl) {
+        var url = redirectUrl ? redirectUrl : "/article/"+id;
         return "<p class=\"chat-mess-time\">刚刚</p>\n" +
-            "              <a href='/article/"+id+"' target='_blank'>" +
+            "              <a href='"+url+"' target='_blank'>" +
             "                <div class=\"public-account-mess-container\">" +
             "                   <div class=\"public-account-mess-cover-container\">" +
             "                       <img src=\""+img+"\" class='public-account-mess-cover'>"+

+ 59 - 3
src/main/resources/templates/client/lottery.html

@@ -22,9 +22,65 @@
             background-color: transparent;/*背景透明*/
             box-shadow: 0 0 0 rgba(0,0,0,0);/*前景无阴影*/
         }
+        .popup {
+            background-color: transparent;/*背景透明*/
+            box-shadow: 0 0 0 rgba(0,0,0,0);/*前景无阴影*/
+        }
+        .close-popup-btn {
+            width: 30px;
+            height: 30px;
+            background-color: transparent;
+            border: 2px solid white;
+            border-radius: 100px;
+        }
+        .userOrderMaxHeight {
+            max-height: 420px;
+            overflow-y: hidden;
+        }
+        #time1LuckBtn {
+            position: absolute;
+            right: 30px;
+            top: 30px;
+            height: 70px;
+            width: 200px;
+            border: none;
+            border-radius: 5px;
+            font-size: 20px;
+            color: white;
+            font-weight: 600;
+            box-shadow: 0px 0px 10px #dedede;
+            background: #11998e;  /* fallback for old browsers */      background: -webkit-linear-gradient(to right, rgb(17, 153, 142), rgb(56, 239, 125));  /* Chrome 10-25, Safari 5.1-6 */      background: linear-gradient(to right, rgb(17, 153, 142), rgb(56, 239, 125)); /* W3C, IE 10+/ Edge, Firefox 16+, Chrome 26+, Opera 12+, Safari 7+ */
+        }
+        #time10LuckBtn {
+            position: absolute;
+            left: 30px;
+            top: 30px;
+            height: 70px;
+            width: 250px;
+            border: none;
+            border-radius: 5px;
+            font-size: 20px;
+            color: white;
+            font-weight: 600;
+            background: #360033;  /* fallback for old browsers */      background: -webkit-linear-gradient(to right, rgb(54, 0, 51), rgb(11, 135, 147));  /* Chrome 10-25, Safari 5.1-6 */      background: linear-gradient(to right, rgb(54, 0, 51), rgb(11, 135, 147)); /* W3C, IE 10+/ Edge, Firefox 16+, Chrome 26+, Opera 12+, Safari 7+ */
+            box-shadow: 0px 0px 10px #dedede;
+        }
+        #time1LuckBtn img, #time10LuckBtn img {
+            margin: 0px 5px 0px 15px;
+        }
+        .time10result-container {
+            position: relative;
+            width: 120px;
+            background-color: transparent;
+            height: 120px;
+            float: left;
+            margin: 0px 0px 30px 0px;
+            text-align: center;
+            overflow: hidden;
+        }
     </style>
 </head>
-<body>
+<body style="background-color: whitesmoke">
 <center>
 
     <div id="header" style="position: fixed; top: 0px; left: 0px; width: 100%; height: 60px; z-index: 1999"></div>
@@ -378,7 +434,7 @@
                 "</div>"+
                 "<p style='width: 500px; height: 30px; margin-top: 20px; text-align: center'>" +
                 "<button onclick='layer.closeAll()' class='close-popup-btn'>" +
-                "<i class=\"layui-icon\" style='font-size: 20px; color: white'>&#x1006;</i>" +
+                "<i class=\"layui-icon\" style='font-size: 20px; color: white'>&#x1007;</i>" +
                 "</button></p>";
             layer.open({
                 type: 1,
@@ -400,7 +456,7 @@
             popupContent += "</div>"+
                 "<p style='width: 600px; height: 30px; margin-top: 20px; text-align: center'>" +
                 "<button onclick='layer.closeAll()' class='close-popup-btn'>" +
-                "<i class=\"layui-icon\" style='font-size: 20px; color: white'>&#x1006;</i>" +
+                "<i class=\"layui-icon\" style='font-size: 20px; color: white'>&#x1007;</i>" +
                 "</button></p>";
             layer.open({
                 type: 1,

+ 11 - 0
src/main/resources/templates/client/writer.html

@@ -273,6 +273,15 @@
             <div style="clear: both"></div>
         </div>
         <div class="editor-ext">
+            <div class="editor-ext-title2">外部链接(非必填)</div>
+            <div class="editor-sign-box">
+                <input class="editor-sign-box" type="text" name="" id="redirect-url"
+                       placeholder="如果指定外部链接则优先跳转到指定链接地址"
+                       autocomplete="off" style="border: none; text-indent: 10px">
+            </div>
+            <div style="clear: both"></div>
+        </div>
+        <div class="editor-ext">
             <div class="editor-ext-title2">文章标签</div>
             <div class="editor-sign-box">
                 <input class="editor-sign-box" type="text" name="" id="editor-input-tags"
@@ -436,6 +445,7 @@
         var description = $("#editor-description-input").val();
         var cover = $("#editor-cover-image").attr("src");
         var signs = $("#editor-input-tags").val();
+        var redirectUrl = $("#redirect-url").val();
         var content = $("#content").html();
         if (publicAccount == '') {
             layer.msg("请先选择公众号");
@@ -476,6 +486,7 @@
                 description: description,
                 cover: cover,
                 content: content,
+                redirectUrl: redirectUrl,
                 planPushTime: planPushTime
             }),
             success: function (data) {