Forráskód Böngészése

feat:1.专题管理;2.投诉管理;3.WebSocket消息通知机制

shanshan 2 éve
szülő
commit
66c302f80a
19 módosított fájl, 495 hozzáadás és 6 törlés
  1. 4 0
      pom.xml
  2. 1 1
      src/main/java/cn/seecoder/fdroidrepository/Controller/BuildController.java
  3. 68 0
      src/main/java/cn/seecoder/fdroidrepository/Controller/ManageController.java
  4. 6 1
      src/main/java/cn/seecoder/fdroidrepository/DataObject/Enum/ResultCode.java
  5. 21 0
      src/main/java/cn/seecoder/fdroidrepository/DataObject/PO/ComplaintPO.java
  6. 10 0
      src/main/java/cn/seecoder/fdroidrepository/DataObject/PO/ConfigPO.java
  7. 28 0
      src/main/java/cn/seecoder/fdroidrepository/DataObject/VO/ComplaintVO.java
  8. 13 0
      src/main/java/cn/seecoder/fdroidrepository/DataObject/VO/ConfigUpdateVO.java
  9. 18 0
      src/main/java/cn/seecoder/fdroidrepository/DataObject/VO/search/ComplaintSearchVO.java
  10. 28 0
      src/main/java/cn/seecoder/fdroidrepository/Mapper/ComplaintMapper.java
  11. 15 0
      src/main/java/cn/seecoder/fdroidrepository/Mapper/ConfigMapper.java
  12. 12 0
      src/main/java/cn/seecoder/fdroidrepository/Service/ComplaintService.java
  13. 8 0
      src/main/java/cn/seecoder/fdroidrepository/Service/ConfigService.java
  14. 90 0
      src/main/java/cn/seecoder/fdroidrepository/Service/ServiceImpl/ComplaintServiceImpl.java
  15. 39 0
      src/main/java/cn/seecoder/fdroidrepository/Service/ServiceImpl/ConfigServiceImpl.java
  16. 15 0
      src/main/java/cn/seecoder/fdroidrepository/websocket/WebSocketConfig.java
  17. 84 0
      src/main/java/cn/seecoder/fdroidrepository/websocket/WebSocketService.java
  18. 4 4
      src/main/resources/mapper/BugMapper.xml
  19. 31 0
      src/main/resources/mapper/ComplaintMapper.xml

+ 4 - 0
pom.xml

@@ -112,6 +112,10 @@
             <artifactId>opencc4j</artifactId>
             <artifactId>opencc4j</artifactId>
             <version>1.8.1</version>
             <version>1.8.1</version>
         </dependency>
         </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-websocket</artifactId>
+        </dependency>
     </dependencies>
     </dependencies>
 
 
     <build>
     <build>

+ 1 - 1
src/main/java/cn/seecoder/fdroidrepository/Controller/BuildController.java

@@ -34,7 +34,7 @@ public class BuildController {
         return buildService.searchCount(buildTaskSearchVO);
         return buildService.searchCount(buildTaskSearchVO);
     }
     }
 
 
-    @GetMapping("/#{taskId}/status")
+    @GetMapping("/{taskId}/status")
     private Response checkStatus(@PathVariable("taskId") Integer taskId) {
     private Response checkStatus(@PathVariable("taskId") Integer taskId) {
         return buildService.checkTaskStatus(taskId);
         return buildService.checkTaskStatus(taskId);
     }
     }

+ 68 - 0
src/main/java/cn/seecoder/fdroidrepository/Controller/ManageController.java

@@ -0,0 +1,68 @@
+package cn.seecoder.fdroidrepository.Controller;
+
+import cn.seecoder.fdroidrepository.DataObject.Enum.ResultCode;
+import cn.seecoder.fdroidrepository.DataObject.VO.ComplaintVO;
+import cn.seecoder.fdroidrepository.DataObject.VO.ConfigUpdateVO;
+import cn.seecoder.fdroidrepository.DataObject.VO.Response;
+import cn.seecoder.fdroidrepository.DataObject.VO.search.ComplaintSearchVO;
+import cn.seecoder.fdroidrepository.Service.ComplaintService;
+import cn.seecoder.fdroidrepository.Service.ConfigService;
+import cn.seecoder.fdroidrepository.Service.SensitiveWordService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+@RestController
+@RequestMapping("/manage")
+@RequiredArgsConstructor
+public class ManageController {
+    @Autowired
+    private final SensitiveWordService sensitiveWordService;
+
+    private final ConfigService configService;
+    private final ComplaintService complaintService;
+
+
+    @GetMapping("/sensitive/list")
+    public Response listSensitiveWords() {
+        return sensitiveWordService.list();
+    }
+
+    @PostMapping("/sensitive/add")
+    public Response addSensitiveWord(@RequestBody String word) {
+        return sensitiveWordService.add(word);
+    }
+
+    @GetMapping("/config")
+    public Response getConfigValue(@RequestParam("key") String key) {
+        return configService.getValue(key);
+    }
+
+    @PostMapping("/config")
+    public Response updateConfig(@RequestBody ConfigUpdateVO updateVO) {
+        if (updateVO == null) {
+            return Response.buildFailure(ResultCode.ILLEGAL_ARGUMENT.getCode(), ResultCode.ILLEGAL_ARGUMENT.getMessage());
+        }
+        return configService.updateValue(updateVO.getKey(), updateVO.getValue());
+    }
+
+    @PostMapping("/complaint")
+    public Response addComplaint(@RequestBody ComplaintVO complaintVO) {
+        return complaintService.addComplaint(complaintVO);
+    }
+
+    @PostMapping("/complaint/handle")
+    public Response handleComplaint(@RequestParam("id")Integer id, @RequestParam("prove") Boolean prove) {
+        return complaintService.handleComplaint(id, prove);
+    }
+
+    @PostMapping("/complaint/search")
+    public Response searchComplaint(@RequestBody ComplaintSearchVO searchVO) {
+        return complaintService.search(searchVO);
+    }
+
+    @PostMapping("/complaint/count")
+    public Response countComplaint(@RequestBody ComplaintSearchVO searchVO) {
+        return complaintService.searchCount(searchVO);
+    }
+}

+ 6 - 1
src/main/java/cn/seecoder/fdroidrepository/DataObject/Enum/ResultCode.java

@@ -14,7 +14,12 @@ public enum ResultCode {
     // Post 相关的错误代码
     // Post 相关的错误代码
     POST_NON_EXIST(40001, "对应的POST不存在或被删除"),
     POST_NON_EXIST(40001, "对应的POST不存在或被删除"),
     // 敏感词相关错误代码
     // 敏感词相关错误代码
-    SENSITIVE_ADD_ERROR(50001, "添加敏感词错误");
+    SENSITIVE_ADD_ERROR(50001, "添加敏感词错误"),
+    // 配置相关错误代码
+    CONFIG_NON_EXIST(60001, "对应的配置信息不存在"),
+    // 投诉相关错误代码
+    COMPLAINT_NON_EXIST(70001, "对应的投诉不存在"),
+    COMPLAINT_ALREADY_HANDLED(70002, "投诉已经被处理");
     private Integer code;
     private Integer code;
     private String message;
     private String message;
     ResultCode(Integer code, String message) {
     ResultCode(Integer code, String message) {

+ 21 - 0
src/main/java/cn/seecoder/fdroidrepository/DataObject/PO/ComplaintPO.java

@@ -0,0 +1,21 @@
+package cn.seecoder.fdroidrepository.DataObject.PO;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.Date;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class ComplaintPO {
+    private Integer id;
+    private Integer postId;
+    private Integer createrId;
+    private String reason;
+    private boolean handled;
+
+    private Date createTime;
+    private Date updateTime;
+}

+ 10 - 0
src/main/java/cn/seecoder/fdroidrepository/DataObject/PO/ConfigPO.java

@@ -0,0 +1,10 @@
+package cn.seecoder.fdroidrepository.DataObject.PO;
+
+import lombok.Data;
+
+@Data
+public class ConfigPO {
+    Integer id;
+    String key;
+    String value;
+}

+ 28 - 0
src/main/java/cn/seecoder/fdroidrepository/DataObject/VO/ComplaintVO.java

@@ -0,0 +1,28 @@
+package cn.seecoder.fdroidrepository.DataObject.VO;
+
+import cn.seecoder.fdroidrepository.DataObject.PO.ComplaintPO;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.springframework.beans.BeanUtils;
+
+import java.util.Date;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class ComplaintVO {
+    private Integer id;
+    private Integer postId;
+    private Integer createrId;
+    private String reason;
+    private boolean handled;
+
+    private Date createTime;
+    private Date updateTime;
+
+    public ComplaintVO(ComplaintPO complaintPO) {
+        BeanUtils.copyProperties(complaintPO, this);
+    }
+
+}

+ 13 - 0
src/main/java/cn/seecoder/fdroidrepository/DataObject/VO/ConfigUpdateVO.java

@@ -0,0 +1,13 @@
+package cn.seecoder.fdroidrepository.DataObject.VO;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class ConfigUpdateVO {
+    String key;
+    String value;
+}

+ 18 - 0
src/main/java/cn/seecoder/fdroidrepository/DataObject/VO/search/ComplaintSearchVO.java

@@ -0,0 +1,18 @@
+package cn.seecoder.fdroidrepository.DataObject.VO.search;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class ComplaintSearchVO {
+    private Integer id;
+    private Integer postId;
+    private Integer handled;
+
+    private Integer pageNum;
+    private Integer pageSize = 10;
+    private Integer start;
+}

+ 28 - 0
src/main/java/cn/seecoder/fdroidrepository/Mapper/ComplaintMapper.java

@@ -0,0 +1,28 @@
+package cn.seecoder.fdroidrepository.Mapper;
+
+import cn.seecoder.fdroidrepository.DataObject.PO.ComplaintPO;
+import cn.seecoder.fdroidrepository.DataObject.VO.search.ComplaintSearchVO;
+import org.apache.ibatis.annotations.InsertProvider;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
+import org.apache.ibatis.annotations.UpdateProvider;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+
+@Repository
+public interface ComplaintMapper {
+
+    @InsertProvider(type = GeneralInsertUpdateSqlProvider.class, method = "insert")
+    Integer insert(@Param("obj") ComplaintPO complaintPO);
+
+    @UpdateProvider(type = GeneralInsertUpdateSqlProvider.class, method = "updateById")
+    Integer update(@Param("obj") ComplaintPO complaintPO);
+
+    @Select("select * from complaint where id = #{id}")
+    ComplaintPO selectById(Integer id);
+
+    List<ComplaintPO> search(ComplaintSearchVO searchVO);
+
+    Integer searchCount(ComplaintSearchVO searchVO);
+}

+ 15 - 0
src/main/java/cn/seecoder/fdroidrepository/Mapper/ConfigMapper.java

@@ -0,0 +1,15 @@
+package cn.seecoder.fdroidrepository.Mapper;
+
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
+import org.apache.ibatis.annotations.Update;
+
+@Mapper
+public interface ConfigMapper {
+    @Select("select value from config where key = #{key}")
+    String getValue(@Param("key") String key);
+
+    @Update("update config set value = #{value} where key = #{key}")
+    Integer updateValue(@Param("key") String key, @Param("value") String value);
+}

+ 12 - 0
src/main/java/cn/seecoder/fdroidrepository/Service/ComplaintService.java

@@ -0,0 +1,12 @@
+package cn.seecoder.fdroidrepository.Service;
+
+import cn.seecoder.fdroidrepository.DataObject.VO.ComplaintVO;
+import cn.seecoder.fdroidrepository.DataObject.VO.Response;
+import cn.seecoder.fdroidrepository.DataObject.VO.search.ComplaintSearchVO;
+
+public interface ComplaintService {
+    Response addComplaint(ComplaintVO complaintVO);
+    Response handleComplaint(Integer id, Boolean prove);
+    Response search(ComplaintSearchVO searchVO);
+    Response searchCount(ComplaintSearchVO searchVO);
+}

+ 8 - 0
src/main/java/cn/seecoder/fdroidrepository/Service/ConfigService.java

@@ -0,0 +1,8 @@
+package cn.seecoder.fdroidrepository.Service;
+
+import cn.seecoder.fdroidrepository.DataObject.VO.Response;
+
+public interface ConfigService {
+    Response updateValue(String key, String value);
+    Response getValue(String key);
+}

+ 90 - 0
src/main/java/cn/seecoder/fdroidrepository/Service/ServiceImpl/ComplaintServiceImpl.java

@@ -0,0 +1,90 @@
+package cn.seecoder.fdroidrepository.Service.ServiceImpl;
+
+import cn.seecoder.fdroidrepository.DataObject.Enum.ResultCode;
+import cn.seecoder.fdroidrepository.DataObject.PO.ComplaintPO;
+import cn.seecoder.fdroidrepository.DataObject.PO.PostPO;
+import cn.seecoder.fdroidrepository.DataObject.VO.ComplaintVO;
+import cn.seecoder.fdroidrepository.DataObject.VO.Response;
+import cn.seecoder.fdroidrepository.DataObject.VO.search.ComplaintSearchVO;
+import cn.seecoder.fdroidrepository.Mapper.ComplaintMapper;
+import cn.seecoder.fdroidrepository.Mapper.PostMapper;
+import cn.seecoder.fdroidrepository.Service.ComplaintService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.beans.BeanUtils;
+import org.springframework.stereotype.Service;
+
+import java.util.Date;
+
+@Service
+@RequiredArgsConstructor
+public class ComplaintServiceImpl implements ComplaintService {
+    private final ComplaintMapper complaintMapper;
+    private final PostMapper postMapper;
+
+    @Override
+    public Response addComplaint(ComplaintVO complaintVO) {
+        if (complaintVO == null) {
+            return Response.buildFailure(ResultCode.ILLEGAL_ARGUMENT.getCode(), ResultCode.ILLEGAL_ARGUMENT.getMessage());
+        }
+        ComplaintPO complaintPO = new ComplaintPO();
+        BeanUtils.copyProperties(complaintVO, complaintPO);
+        complaintPO.setHandled(false);
+        complaintPO.setCreateTime(new Date(System.currentTimeMillis()));
+        return Response.buildSuccess(complaintMapper.insert(complaintPO));
+    }
+
+    @Override
+    public Response handleComplaint(Integer id, Boolean prove) {
+        if (id == null || prove == null) {
+            return Response.buildFailure(ResultCode.ILLEGAL_ARGUMENT.getCode(), ResultCode.ILLEGAL_ARGUMENT.getMessage());
+        }
+        ComplaintPO complaintPO = complaintMapper.selectById(id);
+        if (complaintPO == null) {
+            return Response.buildFailure(ResultCode.COMPLAINT_NON_EXIST.getCode(), ResultCode.COMPLAINT_NON_EXIST.getMessage());
+        }
+        if (complaintPO.isHandled()) {
+            return Response.buildFailure(ResultCode.COMPLAINT_ALREADY_HANDLED.getCode(), ResultCode.COMPLAINT_ALREADY_HANDLED.getMessage());
+        }
+        complaintPO.setHandled(true);
+        complaintMapper.update(complaintPO);
+        if (prove) {
+            // 审核人员支持投诉,需要关闭对应的post,并向对应的作者发送消息
+            PostPO postPO = postMapper.selectById(complaintPO.getPostId());
+            if (postPO == null) {
+                return Response.buildFailure(ResultCode.POST_NON_EXIST.getCode(), ResultCode.POST_NON_EXIST.getMessage());
+            }
+            if (postPO.getValid()) {
+                postPO.setValid(false);
+                postPO.setUpdateTime(new Date(System.currentTimeMillis()));
+                postMapper.update(postPO);
+                // TODO 发送websocket消息
+            }
+        } else {
+            // 审核人员不支持投诉,向投诉者发送信息
+            // TODO 发送websocket信息
+        }
+        return null;
+    }
+
+    @Override
+    public Response search(ComplaintSearchVO searchVO) {
+        if (searchVO == null) {
+            return Response.buildFailure(ResultCode.ILLEGAL_ARGUMENT.getCode(), ResultCode.ILLEGAL_ARGUMENT.getMessage());
+        }
+        if (searchVO.getPageNum() != null) {
+            if (searchVO.getPageNum() < 1 || searchVO.getPageSize() == null) {
+                return Response.buildFailure(ResultCode.ILLEGAL_ARGUMENT.getCode(), ResultCode.ILLEGAL_ARGUMENT.getMessage());
+            }
+            searchVO.setStart((searchVO.getPageNum() - 1) * searchVO.getPageSize());
+        }
+        return Response.buildSuccess(complaintMapper.search(searchVO));
+    }
+
+    @Override
+    public Response searchCount(ComplaintSearchVO searchVO) {
+        if (searchVO == null) {
+            return Response.buildFailure(ResultCode.ILLEGAL_ARGUMENT.getCode(), ResultCode.ILLEGAL_ARGUMENT.getMessage());
+        }
+        return Response.buildSuccess(complaintMapper.searchCount(searchVO));
+    }
+}

+ 39 - 0
src/main/java/cn/seecoder/fdroidrepository/Service/ServiceImpl/ConfigServiceImpl.java

@@ -0,0 +1,39 @@
+package cn.seecoder.fdroidrepository.Service.ServiceImpl;
+
+import cn.seecoder.fdroidrepository.DataObject.Enum.ResultCode;
+import cn.seecoder.fdroidrepository.DataObject.VO.Response;
+import cn.seecoder.fdroidrepository.Mapper.ConfigMapper;
+import cn.seecoder.fdroidrepository.Service.ConfigService;
+import com.github.houbb.heaven.util.lang.StringUtil;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+
+@Service
+@RequiredArgsConstructor
+public class ConfigServiceImpl implements ConfigService {
+    private final ConfigMapper configMapper;
+
+    @Override
+    public Response updateValue(String key, String value) {
+        if (StringUtil.isEmpty(key) || StringUtil.isEmpty(value)) {
+            return Response.buildFailure(ResultCode.ILLEGAL_ARGUMENT.getCode(), ResultCode.ILLEGAL_ARGUMENT.getMessage());
+        }
+        String oldValue = configMapper.getValue(key);
+        if (StringUtil.isEmpty(oldValue)) {
+            return Response.buildFailure(ResultCode.CONFIG_NON_EXIST.getCode(), ResultCode.CONFIG_NON_EXIST.getMessage());
+        }
+        return Response.buildSuccess(configMapper.updateValue(key, value));
+    }
+
+    @Override
+    public Response getValue(String key) {
+        if (StringUtil.isEmpty(key)) {
+            return Response.buildFailure(ResultCode.ILLEGAL_ARGUMENT.getCode(), ResultCode.ILLEGAL_ARGUMENT.getMessage());
+        }
+        String result = configMapper.getValue(key);
+        if (StringUtil.isEmpty(result)) {
+            return Response.buildFailure(ResultCode.CONFIG_NON_EXIST.getCode(), ResultCode.CONFIG_NON_EXIST.getMessage());
+        }
+        return Response.buildSuccess(result);
+    }
+}

+ 15 - 0
src/main/java/cn/seecoder/fdroidrepository/websocket/WebSocketConfig.java

@@ -0,0 +1,15 @@
+package cn.seecoder.fdroidrepository.websocket;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.socket.config.annotation.EnableWebSocket;
+import org.springframework.web.socket.server.standard.ServerEndpointExporter;
+
+@Configuration
+@EnableWebSocket
+public class WebSocketConfig {
+    @Bean
+    public ServerEndpointExporter serverEndpointExporter() {
+        return new ServerEndpointExporter();
+    }
+}

+ 84 - 0
src/main/java/cn/seecoder/fdroidrepository/websocket/WebSocketService.java

@@ -0,0 +1,84 @@
+package cn.seecoder.fdroidrepository.websocket;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+import org.springframework.web.socket.WebSocketMessage;
+import org.springframework.web.socket.WebSocketSession;
+
+import javax.websocket.*;
+import javax.websocket.server.PathParam;
+import javax.websocket.server.ServerEndpoint;
+import java.io.IOException;
+import java.util.LinkedList;
+import java.util.Queue;
+import java.util.concurrent.ConcurrentHashMap;
+
+@Component
+@ServerEndpoint("/message/{userId}")
+public class WebSocketService {
+    // 用户连接池存储
+    private static ConcurrentHashMap<Integer, Session> SESSION_POLL = new ConcurrentHashMap<>();
+
+    // 用户历史消息保存,保存未登录时存储的消息
+    private static ConcurrentHashMap<Integer, Queue<String>> HISTORY_MESSAGE = new ConcurrentHashMap<>();
+
+    private static final Logger logger = LoggerFactory.getLogger(WebSocketService.class);
+
+    @OnOpen
+    public void onOpen(Session session, @PathParam("userId") Integer userId) {
+        if (!SESSION_POLL.contains(userId)) {
+            SESSION_POLL.put(userId, session);
+        }
+        // 历史数据
+        if (HISTORY_MESSAGE.contains(userId)) {
+            Queue<String> history = HISTORY_MESSAGE.get(userId);
+            if (history.size() > 0) {
+                for (String text : history) {
+                    try {
+                        session.getBasicRemote().sendText(text);
+                    } catch (IOException exception) {
+                        logger.error("发送历史消息失败,userId: {}, message: {}, exception: {}", userId, text, exception.getMessage());
+                    }
+                }
+            }
+            HISTORY_MESSAGE.remove(userId);
+        }
+    }
+
+    @OnClose
+    public void onClose(@PathParam("userId") Integer userId) {
+        SESSION_POLL.remove(userId);
+    }
+
+    @OnMessage
+    public void onMessage(String message) {
+        logger.info("WebSocket 收到信息:{}", message);
+        if (message.indexOf("ToUser:") == 0) {
+            String targetId = message.substring(message.indexOf("ToUser:") + 7, message.indexOf(";"));
+            message = message.substring(message.indexOf(";"));
+            Integer target = Integer.valueOf(targetId);
+            if (SESSION_POLL.contains(target)) {
+                try {
+                    SESSION_POLL.get(target).getBasicRemote().sendText(message);
+                } catch (IOException exception) {
+                    logger.error("发送历史消息失败, message: {}, exception: {}", message, exception.getMessage());
+                }
+            } else {
+                // 用户未登录,加入历史记录列表
+                if (HISTORY_MESSAGE.contains(target)) {
+                    HISTORY_MESSAGE.get(target).add(message);
+                } else {
+                    Queue<String> queue = new LinkedList<>();
+                    queue.add(message);
+                    HISTORY_MESSAGE.put(target, queue);
+                }
+            }
+        }
+    }
+
+    @OnError
+    public void onError(Session session, Throwable error) {
+        logger.error("WebSocket Server出现错误,{}", error.getMessage());
+    }
+}

+ 4 - 4
src/main/resources/mapper/BugMapper.xml

@@ -16,8 +16,8 @@
     <select id="search" resultMap="BugResultMap" parameterType="cn.seecoder.fdroidrepository.DataObject.VO.search.BugSearchVO">
     <select id="search" resultMap="BugResultMap" parameterType="cn.seecoder.fdroidrepository.DataObject.VO.search.BugSearchVO">
         select * from bug where 1=1
         select * from bug where 1=1
             <if test="id != null">and id = #{id}</if>
             <if test="id != null">and id = #{id}</if>
-            <if test="app_id != null">and app_id = #{appId}</if>
-            <if test="user_id != null">and user_id = #{userId}</if>
+            <if test="appId != null">and app_id = #{appId}</if>
+            <if test="userId != null">and user_id = #{userId}</if>
             <if test="fixed != null">and fixed = #{fixed}</if>
             <if test="fixed != null">and fixed = #{fixed}</if>
         order by create_time desc
         order by create_time desc
         <if test="start != null">
         <if test="start != null">
@@ -28,8 +28,8 @@
     <select id="searchCount" resultType="java.lang.Integer" parameterType="cn.seecoder.fdroidrepository.DataObject.VO.search.BugSearchVO">
     <select id="searchCount" resultType="java.lang.Integer" parameterType="cn.seecoder.fdroidrepository.DataObject.VO.search.BugSearchVO">
         select count(id) from bug where 1=1
         select count(id) from bug where 1=1
         <if test="id != null">and id = #{id}</if>
         <if test="id != null">and id = #{id}</if>
-        <if test="app_id != null">and app_id = #{appId}</if>
-        <if test="user_id != null">and user_id = #{userId}</if>
+        <if test="appId != null">and app_id = #{appId}</if>
+        <if test="userId != null">and user_id = #{userId}</if>
         <if test="fixed != null">and fixed = #{fixed}</if>
         <if test="fixed != null">and fixed = #{fixed}</if>
     </select>
     </select>
 </mapper>
 </mapper>

+ 31 - 0
src/main/resources/mapper/ComplaintMapper.xml

@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="cn.seecoder.fdroidrepository.Mapper.ComplaintMapper">
+    <resultMap id="ComplaintResultMap" type="cn.seecoder.fdroidrepository.DataObject.PO.ComplaintPO">
+        <id column="id" property="id"/>
+        <result column="post_id" property="postId"/>
+        <result column="creater_id" property="createrId"/>
+        <result column="reason" property="reason"/>
+        <result column="handled" property="handled"/>
+        <result column="create_time" property="createTime"/>
+        <result column="update_time" property="updateTime"/>
+    </resultMap>
+
+    <select id="search">
+        select * from complaint where 1 = 1
+            <if test="id != null">and id = #{id}</if>
+            <if test="postId != null">and post_id = #{postId}</if>
+            <if test="handled != null">and handled = #{handled}</if>
+        order by create_time desc
+        <if test="start != null">
+            limit #{start}, #{pageSize}
+        </if>
+    </select>
+
+    <select id="searchCount">
+        select count(id) from complaint where 1 = 1
+            <if test="id != null">and id = #{id}</if>
+            <if test="postId != null">and post_id = #{postId}</if>
+            <if test="handled != null">and handled = #{handled}</if>
+    </select>
+</mapper>