Ver código fonte

新增短信验证码逻辑
修复获取文章评论和图片不存在的bug

fangzhen 7 meses atrás
pai
commit
100648f492

+ 28 - 18
ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CaptchaController.java

@@ -2,13 +2,18 @@ package com.ruoyi.web.controller.common;
 
 import java.awt.image.BufferedImage;
 import java.io.IOException;
+import java.util.Random;
+import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeUnit;
 import javax.annotation.Resource;
 import javax.imageio.ImageIO;
 import javax.servlet.http.HttpServletResponse;
+
+import com.ruoyi.generator.util.SendSms;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.util.FastByteArrayOutputStream;
 import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RestController;
 import com.google.code.kaptcha.Producer;
 import com.ruoyi.common.config.RuoYiConfig;
@@ -22,12 +27,11 @@ import com.ruoyi.system.service.ISysConfigService;
 
 /**
  * 验证码操作处理
- * 
+ *
  * @author ruoyi
  */
 @RestController
-public class CaptchaController
-{
+public class CaptchaController {
     @Resource(name = "captchaProducer")
     private Producer captchaProducer;
 
@@ -36,20 +40,19 @@ public class CaptchaController
 
     @Autowired
     private RedisCache redisCache;
-    
+
     @Autowired
     private ISysConfigService configService;
+
     /**
      * 生成验证码
      */
     @GetMapping("/captchaImage")
-    public AjaxResult getCode(HttpServletResponse response) throws IOException
-    {
+    public AjaxResult getCode(HttpServletResponse response) throws IOException {
         AjaxResult ajax = AjaxResult.success();
         boolean captchaEnabled = configService.selectCaptchaEnabled();
         ajax.put("captchaEnabled", captchaEnabled);
-        if (!captchaEnabled)
-        {
+        if (!captchaEnabled) {
             return ajax;
         }
 
@@ -62,15 +65,12 @@ public class CaptchaController
 
         // 生成验证码
         String captchaType = RuoYiConfig.getCaptchaType();
-        if ("math".equals(captchaType))
-        {
+        if ("math".equals(captchaType)) {
             String capText = captchaProducerMath.createText();
             capStr = capText.substring(0, capText.lastIndexOf("@"));
             code = capText.substring(capText.lastIndexOf("@") + 1);
             image = captchaProducerMath.createImage(capStr);
-        }
-        else if ("char".equals(captchaType))
-        {
+        } else if ("char".equals(captchaType)) {
             capStr = code = captchaProducer.createText();
             image = captchaProducer.createImage(capStr);
         }
@@ -78,12 +78,9 @@ public class CaptchaController
         redisCache.setCacheObject(verifyKey, code, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES);
         // 转换流信息写出
         FastByteArrayOutputStream os = new FastByteArrayOutputStream();
-        try
-        {
+        try {
             ImageIO.write(image, "jpg", os);
-        }
-        catch (IOException e)
-        {
+        } catch (IOException e) {
             return AjaxResult.error(e.getMessage());
         }
 
@@ -91,4 +88,17 @@ public class CaptchaController
         ajax.put("img", Base64.encode(os.toByteArray()));
         return ajax;
     }
+
+    @GetMapping("/captchaCode")
+    public AjaxResult getSmsCode(String phoneNumber) throws ExecutionException, InterruptedException {
+        //1.生成随机四位验证码
+        Random random = new Random();
+        int code = 1000 + random.nextInt(9000);
+        //2.发送验证码
+        SendSms.sendMsg("次元时代", "SMS_474845159", phoneNumber, String.valueOf(code));
+        //3.存入redis
+        String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + code;
+        redisCache.setCacheObject(verifyKey, code, Constants.SMS_EXPIRATION, TimeUnit.MINUTES);
+        return AjaxResult.success("短信验证码发送成功!");
+    }
 }

+ 26 - 13
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java

@@ -2,6 +2,7 @@ package com.ruoyi.web.controller.system;
 
 import java.util.List;
 import java.util.Set;
+
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.PostMapping;
@@ -19,12 +20,11 @@ import com.ruoyi.system.service.ISysMenuService;
 
 /**
  * 登录验证
- * 
+ *
  * @author ruoyi
  */
 @RestController
-public class SysLoginController
-{
+public class SysLoginController {
     @Autowired
     private SysLoginService loginService;
 
@@ -36,29 +36,43 @@ public class SysLoginController
 
     /**
      * 登录方法
-     * 
+     *
      * @param loginBody 登录信息
      * @return 结果
      */
     @PostMapping("/login")
-    public AjaxResult login(@RequestBody LoginBody loginBody)
-    {
+    public AjaxResult login(@RequestBody LoginBody loginBody) {
+        AjaxResult ajax = AjaxResult.success();
+        // 生成令牌
+        String token = loginService.login(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(),
+                loginBody.getUuid(), false);
+        ajax.put(Constants.TOKEN, token);
+        return ajax;
+    }
+
+    /**
+     * 登录方法
+     *
+     * @param loginBody 登录信息
+     * @return 结果
+     */
+    @PostMapping("/loginCommunity")
+    public AjaxResult loginCommunity(@RequestBody LoginBody loginBody) {
         AjaxResult ajax = AjaxResult.success();
         // 生成令牌
         String token = loginService.login(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(),
-                loginBody.getUuid());
+                loginBody.getUuid(), true);
         ajax.put(Constants.TOKEN, token);
         return ajax;
     }
 
     /**
      * 获取用户信息
-     * 
+     *
      * @return 用户信息
      */
     @GetMapping("getInfo")
-    public AjaxResult getInfo()
-    {
+    public AjaxResult getInfo() {
         SysUser user = SecurityUtils.getLoginUser().getUser();
         // 角色集合
         Set<String> roles = permissionService.getRolePermission(user);
@@ -73,12 +87,11 @@ public class SysLoginController
 
     /**
      * 获取路由信息
-     * 
+     *
      * @return 路由信息
      */
     @GetMapping("getRouters")
-    public AjaxResult getRouters()
-    {
+    public AjaxResult getRouters() {
         Long userId = SecurityUtils.getUserId();
         List<SysMenu> menus = menuService.selectMenuTreeByUserId(userId);
         return AjaxResult.success(menuService.buildMenus(menus));

+ 2 - 2
ruoyi-admin/src/main/resources/application-druid.yml

@@ -4,9 +4,9 @@ spring:
         type: com.alibaba.druid.pool.DruidDataSource
         driverClassName: com.mysql.cj.jdbc.Driver
         druid:
-            # 主库数据源  47.122.10.161
+            # 主库数据源  47.122.10.161 121.4.140.159
             master:
-                url: jdbc:mysql://121.4.140.159:3306/ruoyi-community?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+                url: jdbc:mysql://47.122.10.161:3306/ruoyi-community?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
                 username: root
                 password: fangzhen,7410
             # 从库数据源

+ 2 - 2
ruoyi-admin/src/main/resources/application.yml

@@ -67,8 +67,8 @@ spring:
       enabled: true
   # redis 配置
   redis:
-    # 地址 47.122.10.161
-    host: 121.4.140.159
+    # 地址 47.122.10.161 121.4.140.159
+    host: 47.122.10.161
     # 端口,默认为6379
     port: 6379
     # 数据库索引

+ 5 - 0
ruoyi-common/src/main/java/com/ruoyi/common/constant/CacheConstants.java

@@ -17,6 +17,11 @@ public class CacheConstants
      */
     public static final String CAPTCHA_CODE_KEY = "captcha_codes:";
 
+    /**
+     * 短信验证码 redis key
+     */
+    public static final String SMS_CODE_KEY = "sms_codes:";
+
     /**
      * 参数管理 cache key
      */

+ 5 - 0
ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java

@@ -95,6 +95,11 @@ public class Constants
      */
     public static final Integer CAPTCHA_EXPIRATION = 2;
 
+    /**
+     * 短信验证码有效期(分钟)
+     */
+    public static final Integer SMS_EXPIRATION = 5;
+
     /**
      * 令牌
      */

+ 16 - 0
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginBody.java

@@ -1,5 +1,7 @@
 package com.ruoyi.common.core.domain.model;
 
+import com.baomidou.mybatisplus.annotation.TableField;
+
 /**
  * 用户登录对象
  * 
@@ -22,6 +24,12 @@ public class LoginBody
      */
     private String code;
 
+    /**
+     * 短信验证码
+     */
+    @TableField(exist = false)
+    private String smsCode;
+
     /**
      * 唯一标识
      */
@@ -57,6 +65,14 @@ public class LoginBody
         this.code = code;
     }
 
+    public String getSmsCode() {
+        return smsCode;
+    }
+
+    public void setSmsCode(String smsCode) {
+        this.smsCode = smsCode;
+    }
+
     public String getUuid()
     {
         return uuid;

+ 55 - 0
ruoyi-common/src/main/java/com/ruoyi/common/utils/bean/JSONTypeHandler.java

@@ -0,0 +1,55 @@
+package com.ruoyi.common.utils.bean;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.ibatis.type.BaseTypeHandler;
+import org.apache.ibatis.type.JdbcType;
+
+import java.sql.*;
+import java.util.List;
+import java.util.Map;
+
+public class JSONTypeHandler extends BaseTypeHandler<List<Map<String, Object>>> {
+    private static final ObjectMapper objectMapper = new ObjectMapper();
+
+    @Override
+    public void setNonNullParameter(PreparedStatement ps, int i, List<Map<String, Object>> parameter, JdbcType jdbcType) throws SQLException {
+        try {
+            ps.setString(i, objectMapper.writeValueAsString(parameter));
+        } catch (JsonProcessingException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Override
+    public List<Map<String, Object>> getNullableResult(ResultSet rs, String columnName) throws SQLException {
+        String json = rs.getString(columnName);
+        try {
+            return objectMapper.readValue(json, new TypeReference<List<Map<String, Object>>>() {});
+        } catch (JsonProcessingException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Override
+    public List<Map<String, Object>> getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
+        String json = rs.getString(columnIndex);
+        try {
+            return objectMapper.readValue(json, new TypeReference<List<Map<String, Object>>>() {});
+        } catch (JsonProcessingException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Override
+    public List<Map<String, Object>> getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
+        String json = cs.getString(columnIndex);
+        try {
+            return objectMapper.readValue(json, new TypeReference<List<Map<String, Object>>>() {});
+        } catch (JsonProcessingException e) {
+            throw new RuntimeException(e);
+        }
+    }
+}
+

+ 1 - 1
ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java

@@ -61,7 +61,7 @@ public class SysLoginService
      * @param uuid 唯一标识
      * @return 结果
      */
-    public String login(String username, String password, String code, String uuid)
+    public String login(String username, String password, String code, String uuid , boolean isCommunity)
     {
         // 验证码校验
         validateCaptcha(username, code, uuid);

+ 30 - 0
ruoyi-generator/src/main/java/com/ruoyi/generator/controller/CommunityArticleController.java

@@ -84,6 +84,15 @@ public class CommunityArticleController extends BaseController {
         return AjaxResult.success(communityClasses);
     }
 
+    @GetMapping("/circleList")
+    @ApiOperation("获取文章分类列表")
+    //@Anonymous
+    public AjaxResult getCircleList() {
+        List<CommunityCircle> communityClasses = communityCircleMapper.selectList(new QueryWrapper<CommunityCircle>());
+        return AjaxResult.success(communityClasses);
+    }
+
+
     @ApiOperation("文章评价")
     @PostMapping("/comment")
     public AjaxResult comment(@RequestBody CommunityArticleComment communityArticleComment) throws ParseException {
@@ -101,6 +110,27 @@ public class CommunityArticleController extends BaseController {
         return AjaxResult.success();
     }
 
+    @ApiOperation("文章评价")
+    @DeleteMapping("/comment")
+    public AjaxResult deleteComment(@RequestBody CommunityArticleComment communityArticleComment) {
+//        if (null == communityArticleComment.getArticleId()) {
+//            return AjaxResult.error("文章不存在或异常!");
+//        }
+
+        if (null == communityArticleComment.getUserId()) {
+            return AjaxResult.error("用户不存在或异常!");
+        }
+
+        if (!SecurityUtils.getUserId().equals(communityArticleComment.getUserId())) {
+            return AjaxResult.error("不允许删除别人的评论!");
+        }
+
+        //删除评论
+        communityArticleService.deleteComment(communityArticleComment);
+
+        return AjaxResult.success();
+    }
+
     /**
      * 文章点赞
      */

+ 27 - 16
ruoyi-generator/src/main/java/com/ruoyi/generator/service/CommunityArticleServiceImpl.java

@@ -18,10 +18,7 @@ import org.springframework.stereotype.Service;
 import java.net.HttpURLConnection;
 import java.net.URL;
 import java.text.ParseException;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Objects;
+import java.util.*;
 import java.util.stream.Collectors;
 
 /**
@@ -102,12 +99,12 @@ public class CommunityArticleServiceImpl extends ServiceImpl<CommunityArticleMap
         int offset = (pageNum - 1) * pageSize;
         List<CommunityArticleVo> communityArticleVos = communityArticleMapper.selectCommunityArticleList(communityArticle, circleIds, offset, pageSize);
         for (CommunityArticleVo articleVo : communityArticleVos) {
-            List<CommunityArticleImages> imageList = articleVo.getImageList();
+            List<Map<String, Object>> imageList = articleVo.getImageList();
             List<CommunityArticleImages> videoList = new ArrayList<>();
             CommunityArticleImages videos = null;
-            for (CommunityArticleImages image : imageList) {
+            for (Map<String, Object> image : imageList) {
                 videos = new CommunityArticleImages();
-                String imageUrl = image.getImageUrl();
+                String imageUrl = image.get("imageUrl").toString();
                 //判断是否是视频
                 boolean isVideo = isVideoFile(imageUrl);
                 if (isVideo) {
@@ -130,22 +127,26 @@ public class CommunityArticleServiceImpl extends ServiceImpl<CommunityArticleMap
                     .size());
 
             //文章下的评论
-            List<CommunityArticleCommentVo> comments = articleVo.getComments();
-            for (CommunityArticleCommentVo communityArticleCommentVo : comments) {
+            List<Map<String, Object>> comments = articleVo.getComments();
+            for (Map<String, Object> communityArticleCommentVo : comments) {
+                String commentUserId = communityArticleCommentVo.get("userId").toString();
+                if (Objects.isNull(commentUserId)) {
+                    break;
+                }
                 //获取评论的用户信息
-                SysUser sysUser = sysUserMapper.selectUserById(communityArticleCommentVo.getUserId());
-                communityArticleCommentVo.setUsername(sysUser.getUserName());
-                communityArticleCommentVo.setAvatar(sysUser.getAvatar());
+                SysUser sysUser = sysUserMapper.selectUserById(Long.parseLong(commentUserId));
+                communityArticleCommentVo.put("username", sysUser.getUserName());
+                communityArticleCommentVo.put("avatar", sysUser.getAvatar());
                 //当前登录用户是否已点赞
                 List<CommunityCommentLike> commentLikes = communityCommentLikeMapper
                         .selectList(new QueryWrapper<CommunityCommentLike>()
-                                .eq("comment_id", communityArticleCommentVo.getId()).eq("user_id", userId));
-                communityArticleCommentVo.setCommentLike(!commentLikes.isEmpty());
+                                .eq("comment_id", communityArticleCommentVo.get("id")).eq("user_id", userId));
+                communityArticleCommentVo.put("commentLike", !commentLikes.isEmpty());
 
                 //该评论的点赞数量
-                communityArticleCommentVo.setCommentLikeCount(communityCommentLikeMapper
+                communityArticleCommentVo.put("commentLikeCount", communityCommentLikeMapper
                         .selectList(new QueryWrapper<CommunityCommentLike>()
-                                .eq("comment_id", communityArticleCommentVo.getId()))
+                                .eq("comment_id", communityArticleCommentVo.get("id")))
                         .size());
             }
 
@@ -240,6 +241,16 @@ public class CommunityArticleServiceImpl extends ServiceImpl<CommunityArticleMap
         communityArticleCommentMapper.insert(communityArticleComment);
     }
 
+    /**
+     * 删除评论
+     *
+     * @param communityArticleComment 评论信息
+     */
+    @Override
+    public void deleteComment(CommunityArticleComment communityArticleComment) {
+        communityArticleCommentMapper.deleteById(communityArticleComment);
+    }
+
 
     /**
      * 查询该文章对应的用户是否已经点赞

+ 7 - 0
ruoyi-generator/src/main/java/com/ruoyi/generator/service/ICommunityArticleService.java

@@ -38,6 +38,13 @@ public interface ICommunityArticleService extends IService<CommunityArticle> {
      */
     void sendComment(CommunityArticleComment communityArticleComment) throws ParseException;
 
+    /**
+     * 删除评论
+     *
+     * @param communityArticleComment 评论信息
+     */
+    void deleteComment(CommunityArticleComment communityArticleComment);
+
     /**
      * 查询该文章对应的用户是否已经点赞
      *

+ 6 - 3
ruoyi-generator/src/main/java/com/ruoyi/generator/util/SendSms.java

@@ -1,5 +1,6 @@
 package com.ruoyi.generator.util;
 
+import com.alibaba.fastjson2.JSONObject;
 import com.aliyun.auth.credentials.Credential;
 import com.aliyun.auth.credentials.provider.StaticCredentialProvider;
 import com.aliyun.sdk.service.dysmsapi20170525.AsyncClient;
@@ -14,10 +15,12 @@ import java.util.concurrent.ExecutionException;
 
 public class SendSms {
     public static void  sendMsg(String signName, String templateCode, String phoneNumbers, String code) throws ExecutionException, InterruptedException {
+        JSONObject objCode = new JSONObject();
+        objCode.put("code", code);
         StaticCredentialProvider provider = StaticCredentialProvider.create(Credential.builder()
                 // Please ensure that the environment variables ALIBABA_CLOUD_ACCESS_KEY_ID and ALIBABA_CLOUD_ACCESS_KEY_SECRET are set.
-                .accessKeyId(System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"))
-                .accessKeySecret(System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET"))
+                .accessKeyId("LTAI5tHMXA5yqwJfyEcQcnab")
+                .accessKeySecret("yuQEHY1zUXzpJgeG3sRG2b738sfkEy")
                 //.securityToken(System.getenv("ALIBABA_CLOUD_SECURITY_TOKEN")) // use STS token
                 .build());
 
@@ -41,7 +44,7 @@ public class SendSms {
                 .signName(StringUtils.nvl(signName, "社区功能"))
                 .templateCode(StringUtils.nvl(templateCode, "SMS_474645121"))
                 .phoneNumbers(StringUtils.nvl(phoneNumbers, "13358039598"))
-                .templateParam("{\"code\":\"" + code + "\"}")
+                .templateParam(objCode.toJSONString())
                 // Request-level configuration rewrite, can set Http request parameters, etc.
                 // .requestConfiguration(RequestConfiguration.create().setHttpHeaders(new HttpHeaders()))
                 .build();

+ 5 - 2
ruoyi-generator/src/main/java/com/ruoyi/generator/vo/CommunityArticleVo.java

@@ -17,6 +17,7 @@ import javax.validation.constraints.NotNull;
 import javax.validation.constraints.Size;
 import java.io.Serializable;
 import java.util.List;
+import java.util.Map;
 
 /**
 * 
@@ -92,14 +93,16 @@ public class CommunityArticleVo extends BaseEntity implements Serializable {
 //    private List<SysUser> sysUsers;
 
     @ApiModelProperty("文章图片集合")
-    private List<CommunityArticleImages> imageList;
+    @TableField("imageList")
+    private List<Map<String, Object>> imageList;
 
     @ApiModelProperty("文章视频集合")
     @TableField(exist = false)
     private List<CommunityArticleImages> videoList;
 
     @ApiModelProperty("文章评论信息")
-    private List<CommunityArticleCommentVo> comments;
+    @TableField("comments")
+    private List<Map<String, Object>> comments;
 
     @ApiModelProperty("文章标签")
     private List<CommunityTag> tags;

+ 41 - 21
ruoyi-generator/src/main/resources/mapper/community/ArticleMapper.xml

@@ -19,8 +19,8 @@
         <result property="nickName" column="nick_name"/>
         <result property="email" column="email"/>
         <result property="avatar" column="avatar"/>
-        <collection property="imageList" javaType="java.util.List" resultMap="CommunityArticleImagesResult"/>
-        <collection property="comments" resultMap="CommunityCommentsResult"/>
+        <result column="images" property="imageList" javaType="java.util.List" typeHandler="com.ruoyi.common.utils.bean.JSONTypeHandler"/>
+        <result column="comments" property="comments" typeHandler="com.ruoyi.common.utils.bean.JSONTypeHandler"/>
     </resultMap>
 
     <resultMap type="CommunityArticleImages" id="CommunityArticleImagesResult">
@@ -108,38 +108,58 @@
         a.create_time as article_create_time,
         a.update_by as article_update_by,
         a.update_time as article_update_time,
+        COALESCE((
+        SELECT
         JSON_ARRAYAGG(
+        CASE
+        WHEN b.id IS NOT NULL THEN
         JSON_OBJECT(
-        'image_id', b.id,
-        'images_article_id',b.article_id,
-        'image_url',b.image_url,
-        'images_create_by',b.create_by,
-        'images_create_time',b.create_time,
-        'images_update_by',b.update_by,
-        'images_update_time',b.update_time
+        'id', IFNULL(b.id,''),
+        'articleId', IFNULL(b.article_id,''),
+        'imageUrl', IFNULL(b.image_url,''),
+        'createBy', IFNULL(b.create_by,''),
+        'createTime', IFNULL(DATE_FORMAT(b.create_time,'%Y-%m-%d %H:%i:%s'),''),
+        'updateBy', IFNULL(b.update_by,''),
+        'updateTime', IFNULL(DATE_FORMAT(b.update_time,'%Y-%m-%d %H:%i:%s'),'')
         )
-        ) as images,
+        ELSE NULL
+        END
+        )
+        FROM
+        community_article_images b
+        WHERE
+        b.article_id = a.id
+        ), '[]') AS images,
         c.user_name as user_name,
         c.nick_name as nick_name,
         c.email as email,
         c.avatar as avatar,
+        COALESCE((
+        SELECT
         JSON_ARRAYAGG(
+        CASE
+        WHEN d.id IS NOT NULL THEN
         JSON_OBJECT(
-        'comment_id',d.id,
-        'comment_article_id',d.article_id,
-        'comment_user_id',d.user_id,
-        'comment_content',d.content,
-        'comment_create_by',d.create_by,
-        'comment_create_time',d.create_time,
-        'comment_update_by',d.update_by,
-        'comment_update_time',d.update_time
+        'id', IFNULL(d.id,''),
+        'articleId', IFNULL(d.article_id,''),
+        'userId', IFNULL(d.user_id,''),
+        'content', IFNULL(d.content,''),
+        'createBy', IFNULL(d.create_by,''),
+        'createTime', IFNULL(DATE_FORMAT(d.create_time,'%Y-%m-%d %H:%i:%s'),''),
+        'updateBy', IFNULL(d.update_by,''),
+        'updateTime', IFNULL(DATE_FORMAT(d.update_time,'%Y-%m-%d %H:%i:%s'),'')
+        )
+        ELSE NULL
+        END
         )
-        ) as comments
+        FROM
+        community_article_comment d
+        WHERE
+        d.article_id = a.id
+        ), '[]') AS comments
         from
         community_article a
-        left join community_article_images b on a.id = b.article_id
         left join sys_user c on a.user_id = c.user_id
-        left join community_article_comment d on d.article_id = a.id
         <where>
             <if test="communityArticle.id != null and communityArticle.id != ''">
                 AND a.id = #{communityArticle.id}