Răsfoiți Sursa

资讯与公告,测试完毕

skyfffire 1 lună în urmă
părinte
comite
aa7fcc2893

+ 2 - 0
src/main/java/common/jfinal/AppConfig.java

@@ -11,6 +11,7 @@ import common.interceptor.ExceptionInterceptor;
 import common.interceptor.empty.EmptyInterceptor;
 import common.model._MappingKit;
 import modules.hello.HelloController;
+import modules.news.NewsController;
 import modules.nftt.NfttController;
 import modules.order.OrderController;
 import modules.upload.UploadController;
@@ -54,6 +55,7 @@ public class AppConfig extends JFinalConfig {
         routes.add("/upload", UploadController.class);
         routes.add("/nftt", NfttController.class);
         routes.add("/order", OrderController.class);
+        routes.add("/news", NewsController.class);
     }
 
     @Override

+ 12 - 0
src/main/java/common/model/News.java

@@ -0,0 +1,12 @@
+package common.model;
+
+import common.model.base.BaseNews;
+
+/**
+ * Generated by JFinal.
+ */
+@SuppressWarnings("serial")
+public class News extends BaseNews<News> {
+	public static final News dao = new News().dao();
+}
+

+ 1 - 0
src/main/java/common/model/_MappingKit.java

@@ -17,6 +17,7 @@ public class _MappingKit {
 	
 	public static void mapping(ActiveRecordPlugin arp) {
 		arp.addMapping("t_deposit_log", "id", DepositLog.class);
+		arp.addMapping("t_news", "id", News.class);
 		arp.addMapping("t_nft", "id", Nft.class);
 		arp.addMapping("t_nftt", "id", Nftt.class);
 		arp.addMapping("t_order", "id", Order.class);

+ 128 - 0
src/main/java/common/model/base/BaseNews.java

@@ -0,0 +1,128 @@
+package common.model.base;
+
+import com.jfinal.plugin.activerecord.Model;
+import com.jfinal.plugin.activerecord.IBean;
+
+/**
+ * Generated by JFinal, do not modify this file.
+ */
+@SuppressWarnings("serial")
+public abstract class BaseNews<M extends BaseNews<M>> extends Model<M> implements IBean {
+	/**
+	 * 信息id
+	 */
+	public void setId(java.lang.Integer id) {
+		set("id", id);
+	}
+	
+	/**
+	 * 信息id
+	 */
+	public java.lang.Integer getId() {
+		return getInt("id");
+	}
+	/**
+	 * 类型,1公告2资讯
+	 */
+	public void setType(java.lang.Integer type) {
+		set("type", type);
+	}
+	
+	/**
+	 * 类型,1公告2资讯
+	 */
+	public java.lang.Integer getType() {
+		return getInt("type");
+	}
+	/**
+	 * 图片列表
+	 */
+	public void setImageList(java.lang.String imageList) {
+		set("image_list", imageList);
+	}
+	
+	/**
+	 * 图片列表
+	 */
+	public java.lang.String getImageList() {
+		return getStr("image_list");
+	}
+	/**
+	 * 公告/资讯标题
+	 */
+	public void setTitle(java.lang.String title) {
+		set("title", title);
+	}
+	
+	/**
+	 * 公告/资讯标题
+	 */
+	public java.lang.String getTitle() {
+		return getStr("title");
+	}
+	/**
+	 * 公告/资讯内容
+	 */
+	public void setContent(java.lang.String content) {
+		set("content", content);
+	}
+	
+	/**
+	 * 公告/资讯内容
+	 */
+	public java.lang.String getContent() {
+		return getStr("content");
+	}
+	/**
+	 * 最后操作者
+	 */
+	public void setOperatorId(java.lang.Integer operatorId) {
+		set("operator_id", operatorId);
+	}
+	
+	/**
+	 * 最后操作者
+	 */
+	public java.lang.Integer getOperatorId() {
+		return getInt("operator_id");
+	}
+	public void setCreateTime(java.lang.Long createTime) {
+		set("create_time", createTime);
+	}
+	
+	public java.lang.Long getCreateTime() {
+		return getLong("create_time");
+	}
+	public void setUpdateTime(java.lang.Long updateTime) {
+		set("update_time", updateTime);
+	}
+	
+	public java.lang.Long getUpdateTime() {
+		return getLong("update_time");
+	}
+	public void setIsDeleted(java.lang.Integer isDeleted) {
+		set("is_deleted", isDeleted);
+	}
+	
+	public java.lang.Integer getIsDeleted() {
+		return getInt("is_deleted");
+	}
+	
+	public boolean save() {
+		set("create_time", System.currentTimeMillis());
+		
+		return super.save();
+	}
+	
+	public boolean update() {
+		set("update_time", System.currentTimeMillis());
+		
+		return super.update();
+	}
+
+	public boolean delete() {
+		set("is_deleted", 1);
+
+		return super.update();
+	}
+}

+ 220 - 0
src/main/java/modules/news/NewsController.java

@@ -0,0 +1,220 @@
+package modules.news;
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.jfinal.aop.Before;
+import com.jfinal.aop.Inject;
+import com.jfinal.kit.StrKit;
+import common.interceptor.LoginInterceptor;
+import common.interceptor.empty.EmptyInterface;
+import common.interceptor.role.RequiredRoleInterface;
+import common.model.News;
+import common.utils.http.MyController;
+import common.utils.http.MyRet;
+import modules.user.UserController;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class NewsController extends MyController {
+    @Inject
+    NewsService service;
+
+    public void hello() {
+        renderJson(MyRet.ok(service.hello()));
+    }
+
+    @Before(LoginInterceptor.class)
+    @RequiredRoleInterface({UserController.ROLE_CHECK_ADMIN, UserController.ROLE_SUPER_ADMIN})
+    @EmptyInterface({"type", "image_list", "title", "content"})
+    public void create() {
+        JSONObject requestBodyJson = MyController.getJsonModelByRequestAndType(getRequest(), JSONObject.class);
+        News news = new News();
+
+        // 基础属性设置
+        String currentUserIdStr = getSessionAttr("user_id");
+        if (StrKit.isBlank(currentUserIdStr)) {
+            renderJson(MyRet.fail("创建失败: 未获取到用户信息,请重新登录"));
+            return;
+        }
+        news.setOperatorId(new Integer(currentUserIdStr));
+
+        // 类型
+        Integer type = requestBodyJson.getInteger("type");
+        if (type == null) {
+            // 虽然 EmptyInterface 确保了不为空字符串,但可能为 null
+            renderJson(MyRet.fail("类型(type)不能为空或格式不正确"));
+            return;
+        }
+        if (type != 1 && type != 2) {
+            renderJson(MyRet.fail("类型(type) 只能为 1(公告) 2(资讯)"));
+            return;
+        }
+        news.setType(type);
+
+        // 标题
+        String title = requestBodyJson.getString("title");
+        news.setTitle(title);
+        
+        // 内容
+        String content = requestBodyJson.getString("content");
+        news.setContent(content);
+
+        // 图片数组
+        JSONArray imageList = requestBodyJson.getJSONArray("image_list");
+        if (imageList == null || imageList.isEmpty()) {
+            // EmptyInterface 应该已经保证了 non-null,但可能为空数组
+            // 如果图片列表不能为空,这里可以返回错误
+            renderJson(MyRet.fail("介绍图URL列表(image_list)不能为空"));
+            return;
+        }
+        news.setImageList(imageList.toJSONString());
+        
+        // 老三样初始值设置
+        news.setCreateTime(System.currentTimeMillis());
+        news.setUpdateTime(System.currentTimeMillis());
+        news.setIsDeleted(0);
+
+        if (service.save(news)) {
+            renderJson(MyRet.ok("资讯创建成功").setData(news));
+        } else {
+            renderJson(MyRet.fail("资讯创建失败,原因未知,请将此日志提供给开发者" + news).setData(news));
+        }
+    }
+
+    @Before(LoginInterceptor.class)
+    @RequiredRoleInterface({UserController.ROLE_CHECK_ADMIN, UserController.ROLE_SUPER_ADMIN})
+    @EmptyInterface({"id"})
+    public void update() {
+        JSONObject requestBodyJson = MyController.getJsonModelByRequestAndType(getRequest(), JSONObject.class);
+        String id = requestBodyJson.getString("id");
+
+        News news = service.findNewsById(id);
+
+        if (news == null) {
+            renderJson(MyRet.fail("news模板获取不合法,该id对应的news不存在:" + id));
+            return;
+        }
+        
+        // 基础属性设置
+        String currentUserIdStr = getSessionAttr("user_id");
+        if (StrKit.notBlank(currentUserIdStr)) {
+            news.setOperatorId(new Integer(currentUserIdStr));
+        }
+
+        // 类型
+        Integer type = requestBodyJson.getInteger("type");
+        if (type != null) {
+            if (type != 1 && type != 2) {
+                renderJson(MyRet.fail("类型(type) 只能为 1(公告) 2(资讯)"));
+                return;
+            } else {
+                news.setType(type);
+            }
+        }
+
+        // 标题
+        String title = requestBodyJson.getString("title");
+        if (StrKit.notBlank(title)) {
+            news.setTitle(title);
+        }
+
+        // 内容
+        String content = requestBodyJson.getString("content");
+        if (StrKit.notBlank(content)) {
+            news.setContent(content);
+        }
+
+        // 图片数组
+        JSONArray imageList = requestBodyJson.getJSONArray("image_list");
+        if (imageList != null && !imageList.isEmpty()) {
+            news.setImageList(imageList.toJSONString());
+        }
+        
+        // 更新时间
+        news.setUpdateTime(System.currentTimeMillis());
+
+        // 最后执行更新
+        if (news.update()) {
+            renderJson(MyRet.ok("更新成功").setData(news));
+        } else {
+            renderJson(MyRet.fail("更新失败,请将此日志复制给开发者" + news).setData(news));
+        }
+    }
+
+    @EmptyInterface({"id"})
+    public void findById() {
+        JSONObject requestBodyJson = MyController.getJsonModelByRequestAndType(getRequest(), JSONObject.class);
+
+        String id = requestBodyJson.getString("id");
+        News news = service.findNewsById(id);
+
+        if (news != null) {
+            renderJson(MyRet.ok("获取成功").setData(news));
+        } else {
+            renderJson(MyRet.fail("获取失败,非法请求可能会导致ip封禁!" + id));
+        }
+    }
+
+    @EmptyInterface({"type"})
+    public void homeList() {
+        JSONObject requestBodyJson = MyController.getJsonModelByRequestAndType(getRequest(), JSONObject.class);
+        String type = requestBodyJson.getString("type");
+        
+        renderJson(MyRet.ok("查询成功").setData(service.homeList(type)));
+    }
+    
+    @Before(LoginInterceptor.class)
+    @RequiredRoleInterface({UserController.ROLE_CHECK_ADMIN, UserController.ROLE_SUPER_ADMIN})
+    @EmptyInterface({"page_size", "page_number"})
+    public void newsList() {
+        JSONObject requestBodyJson = MyController.getJsonModelByRequestAndType(getRequest(), JSONObject.class);
+
+        // 页面大小
+        String pageSizeStr = requestBodyJson.getString("page_size");
+        int pageSizeInt;
+        try {
+            pageSizeInt = Integer.parseInt(pageSizeStr);
+
+            if (pageSizeInt <= 0) {
+                renderJson(MyRet.fail("页面大小(page_size)期待是正整数,你传的是: " + pageSizeStr));
+                return;
+            }
+        } catch (Exception e) {
+            renderJson(MyRet.fail("页面大小(page_size)格式不正确: " + e.getMessage()));
+            return;
+        }
+
+        // 页码
+        String pageNumberStr = requestBodyJson.getString("page_number");
+        int pageNumberInt;
+        try {
+            pageNumberInt = Integer.parseInt(pageNumberStr);
+
+            if (pageNumberInt <= 0) {
+                renderJson(MyRet.fail("页码(page_number)期待是正整数,你传的是: " + pageNumberStr));
+                return;
+            }
+        } catch (Exception e) {
+            renderJson(MyRet.fail("页码(page_number)格式不正确: " + e.getMessage()));
+            return;
+        }
+
+        String keywords = requestBodyJson.getString("keywords");
+
+        // 最终结果封装
+        List<News> newsList = service.newsList(pageNumberInt, pageSizeInt, keywords);
+        long newsCount = service.count(keywords);
+
+        Map<String, Object> response = new HashMap<>();
+        response.put("list", newsList);
+        response.put("total_row", newsList.toArray().length);
+        response.put("total_page", 1 + (newsList.toArray().length / pageSizeInt));
+        response.put("page_size", pageSizeInt);
+        response.put("page_number", pageNumberInt);
+        response.put("total_user_count", newsCount);
+
+        renderJson(MyRet.ok("查询成功").setData(response));
+    }
+}

+ 86 - 0
src/main/java/modules/news/NewsService.java

@@ -0,0 +1,86 @@
+package modules.news;
+
+import com.jfinal.kit.StrKit;
+import com.jfinal.plugin.activerecord.Db;
+import common.model.News;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class NewsService {
+    public String hello() {
+        return "Hello news";
+    }
+
+    public boolean save(News news) {
+        return news.save();
+    }
+    
+    public News findNewsById(String id) {
+        return News.dao.findById(id);
+    }
+
+    /**
+     * 查询 NEWS 记录的总数量,支持按名称进行模糊搜索
+     * 如果 keywords 为 null 或空字符串,则返回所有记录的总数。
+     *
+     * @param keywords 可选参数,用于 title 或 content 字段的模糊匹配。
+     * @return 符合条件的 NEWS 记录总数
+     */
+    public long count(String keywords) { // 建议返回 long 类型,防止数量过大 Integer 溢出
+        StringBuilder sqlBuilder = new StringBuilder("SELECT COUNT(id) FROM t_news"); // 使用 COUNT(id) 更明确
+
+        List<Object> params = new ArrayList<>(); // 用于存储 SQL 参数
+
+        // ✅ 添加关键词搜索逻辑
+        if (StrKit.notBlank(keywords)) {
+            sqlBuilder.append(" WHERE title LIKE ? OR content LIKE ? "); // 添加 WHERE 子句
+            params.add("%" + keywords + "%");        // 添加模糊匹配参数
+            params.add("%" + keywords + "%");        // 添加模糊匹配参数
+        }
+
+        // 执行查询
+        // Db.queryLong() 返回 long 类型,更安全
+        return Db.queryLong(sqlBuilder.toString(), params.toArray());
+    }
+
+    public List<News> homeList(String type) {
+        String columns = "*";
+        String baseSql = "select " + columns + " from t_news where type=? order by update_time desc limit 0, 10";
+
+        return News.dao.find(baseSql, type);
+    }
+
+    /**
+     * 分页查询 News 商品列表,并支持按名称模糊搜索
+     *
+     * @param pageNumber 页码
+     * @param pageSize 每页大小
+     * @param keywords 可选参数,用于 title 或 content 字段的模糊匹配。如果为 null 或空字符串则不进行过滤。
+     * @return 符合条件的 News 列表
+     */
+    public List<News> newsList(int pageNumber, int pageSize, String keywords) { // 增加 keywords 参数
+        int offset = (pageNumber - 1) * pageSize;
+
+        String columns = "*";
+        StringBuilder sqlBuilder = new StringBuilder("select ").append(columns).append(" from t_news");
+
+        List<Object> params = new ArrayList<>(); // 用于存储 SQL 参数
+
+        // ✅ 添加关键词搜索逻辑
+        if (StrKit.notBlank(keywords)) {
+            sqlBuilder.append(" WHERE title LIKE ? OR content LIKE ? "); // 添加 WHERE 子句
+            params.add("%" + keywords + "%");        // 添加模糊匹配参数
+            params.add("%" + keywords + "%");        // 添加模糊匹配参数
+        }
+
+        sqlBuilder.append(" order by update_time desc limit ?, ?"); // 添加排序和分页
+        params.add(offset);
+        params.add(pageSize);
+
+        // 执行查询
+        // News.dao.find() 的参数:第一位是 SQL 字符串,后面是可变参数数组
+        // 这里需要将 List<Object> params 转换为 Object[]
+        return News.dao.find(sqlBuilder.toString(), params.toArray());
+    }
+}

+ 1 - 1
src/main/java/modules/nftt/NfttController.java

@@ -169,7 +169,7 @@ public class NfttController extends MyController {
                 }
             } else {
                 renderJson(MyRet.fail("创建失败,原因未知,请将此日志提供给开发者" + nftt).setData(nftt));
-            }            
+            }
         } catch (NumberFormatException e) {
             // 捕获可能发生的数字转换异常
             renderJson(MyRet.fail("参数格式不正确,请检查数字或时间戳字段: " + e.getMessage()));

+ 63 - 0
src/test/rest/NewsControllerTest.http

@@ -0,0 +1,63 @@
+### 连通性测试
+POST {{ baseUrl }}/news/hello
+
+### 查看某一个新闻
+POST {{ baseUrl }}/news/findById
+Content-Type: application/json
+dl-token: {{dl_token_var}}
+
+{
+  "id": 1
+}
+
+### 1:公告信息展示 2:资讯信息展示
+POST {{ baseUrl }}/news/homeList
+Content-Type: application/json
+dl-token: {{dl_token_var}}
+
+{
+  "type": 1
+}
+
+### 【审核管理员、超级管理员】创建news
+POST {{ baseUrl }}/news/create
+Content-Type: application/json
+dl-token: {{dl_token_var}}
+
+# type1是公告,2是资讯
+{
+  "type": 1,
+  "title": "张四丰真迹出土",
+  "content": "在洛阳发现的",
+  "image_list": [
+    "https://jfinal.com/upload/img/share/0/61566_20201109163639.jpg"
+  ]
+}
+
+### 【审核管理员、超级管理员】修改news,传什么字段更新什么,id必传
+POST {{ baseUrl }}/news/update
+Content-Type: application/json
+dl-token: {{dl_token_var}}
+
+{
+  "id": 1,
+  "type": 1
+}
+
+### 【审核管理员、超级管理员】news搜索, keywods用于 title 或 content 字段的模糊匹配
+POST {{ baseUrl }}/news/newsList
+Content-Type: application/json
+dl-token: {{dl_token_var}}
+
+{
+  "page_number": 1,
+  "page_size": 100,
+  "keywords": "洛阳"
+}
+### 返回值解释
+### list 分页结果的实际列表数据 
+### page_number 当前页码
+### page_size 每页大小
+### total_page 总页数
+### total_row  当前分页的总数
+### total_news_count 符合条件的总记录数