web端-新增风采墙模块(工会信息传播与文化展示);

This commit is contained in:
2026-07-30 15:42:06 +08:00
parent ff3e8075b5
commit 5043cee747
22 changed files with 2270 additions and 0 deletions
@@ -0,0 +1,101 @@
package com.budwk.app.zhgh.spread.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import com.budwk.app.base.annotation.SLog;
import com.budwk.app.base.result.Result;
import com.budwk.app.zhgh.spread.models.SpreadCategory;
import com.budwk.app.zhgh.spread.service.SpreadCategoryService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.nutz.aop.interceptor.ioc.TransAop;
import org.nutz.ioc.aop.Aop;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok;
@IocBean
@Ok("json:full")
@Api("风采墙-栏目管理")
@At("/platform/spread/category")
public class SpreadCategoryController {
@Inject
private SpreadCategoryService categoryService;
@At("")
@Ok("beetl:/platform/zhgh/spread/category/index.html")
@SaCheckPermission("spread.category")
public void index() {
}
@At
@ApiOperation("栏目列表")
@SaCheckPermission("spread.category")
public Result listData() {
return Result.success(categoryService.listCategories(false));
}
@At
@ApiOperation("栏目树")
@SaCheckPermission("spread.category")
public Result treeData() {
return Result.success(categoryService.categoryTree(false));
}
@At
@ApiOperation("新增栏目")
@SaCheckPermission("spread.category")
@SLog(tag = "风采墙-栏目管理", msg = "新增栏目:${args[0].name}")
@Aop(TransAop.READ_COMMITTED)
public Result doAdd(SpreadCategory category) {
try {
categoryService.saveCategory(category);
return Result.success();
} catch (RuntimeException e) {
return Result.error(e.getMessage());
}
}
@At
@ApiOperation("编辑栏目")
@SaCheckPermission("spread.category")
@SLog(tag = "风采墙-栏目管理", msg = "编辑栏目:${args[0].id}")
@Aop(TransAop.READ_COMMITTED)
public Result doEdit(SpreadCategory category) {
try {
categoryService.updateCategory(category);
return Result.success();
} catch (RuntimeException e) {
return Result.error(e.getMessage());
}
}
@At
@ApiOperation("删除栏目")
@SaCheckPermission("spread.category")
@SLog(tag = "风采墙-栏目管理", msg = "删除栏目:${args[0]}")
@Aop(TransAop.READ_COMMITTED)
public Result doDelete(String id) {
try {
categoryService.deleteCategory(id);
return Result.success();
} catch (RuntimeException e) {
return Result.error(e.getMessage());
}
}
@At
@ApiOperation("设置栏目显示状态")
@SaCheckPermission("spread.category")
@SLog(tag = "风采墙-栏目管理", msg = "栏目:${args[0]},显示状态:${args[1]}")
@Aop(TransAop.READ_COMMITTED)
public Result doVisible(String id, Integer visible) {
try {
categoryService.setVisible(id, visible);
return Result.success();
} catch (RuntimeException e) {
return Result.error(e.getMessage());
}
}
}
@@ -0,0 +1,81 @@
package com.budwk.app.zhgh.spread.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import com.budwk.app.base.annotation.SLog;
import com.budwk.app.base.result.Result;
import com.budwk.app.zhgh.spread.models.SpreadContent;
import com.budwk.app.zhgh.spread.service.SpreadCategoryService;
import com.budwk.app.zhgh.spread.service.SpreadContentService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.nutz.aop.interceptor.ioc.TransAop;
import org.nutz.ioc.aop.Aop;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok;
@IocBean
@Ok("json:full")
@Api("风采墙-内容发布")
@At("/platform/spread/creation")
public class SpreadCreationController {
@Inject
private SpreadCategoryService categoryService;
@Inject
private SpreadContentService contentService;
@At("")
@Ok("beetl:/platform/zhgh/spread/creation/index.html")
@SaCheckPermission("spread.creation")
public void index() {
}
@At
@ApiOperation("可选栏目树")
@SaCheckPermission("spread.creation")
public Result categoryTree() {
return Result.success(categoryService.categoryTree(true));
}
@At
@ApiOperation("内容详情")
@SaCheckPermission("spread.creation")
public Result detailData(String id) {
try {
return Result.success(contentService.getContent(id));
} catch (RuntimeException e) {
return Result.error(e.getMessage());
}
}
@At
@ApiOperation("新增内容")
@SaCheckPermission("spread.creation")
@SLog(tag = "风采墙-内容发布", msg = "新增内容:${args[0].title}")
@Aop(TransAop.READ_COMMITTED)
public Result doAdd(SpreadContent content) {
try {
contentService.saveContent(content);
return Result.success();
} catch (RuntimeException e) {
return Result.error(e.getMessage());
}
}
@At
@ApiOperation("编辑内容")
@SaCheckPermission("spread.creation")
@SLog(tag = "风采墙-内容发布", msg = "编辑内容:${args[0].id}")
@Aop(TransAop.READ_COMMITTED)
public Result doEdit(SpreadContent content) {
try {
contentService.updateContent(content);
return Result.success();
} catch (RuntimeException e) {
return Result.error(e.getMessage());
}
}
}
@@ -0,0 +1,76 @@
package com.budwk.app.zhgh.spread.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import com.budwk.app.base.param.PageForm;
import com.budwk.app.base.result.Result;
import com.budwk.app.zhgh.spread.service.SpreadCategoryService;
import com.budwk.app.zhgh.spread.service.SpreadContentService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok;
@IocBean
@Ok("json:full")
@Api("风采墙-展示")
@At("/platform/spread/display")
public class SpreadDisplayController {
@Inject
private SpreadCategoryService categoryService;
@Inject
private SpreadContentService contentService;
@At("")
@Ok("beetl:/platform/zhgh/spread/display/index.html")
@SaCheckPermission("spread.display")
public void index() {
}
@At
@ApiOperation("可见栏目树")
@SaCheckPermission("spread.display")
public Result categoryTree() {
return Result.success(categoryService.categoryTree(true));
}
@At
@ApiOperation("已发布内容分页")
@SaCheckPermission("spread.display")
public Result pageData(PageForm pageForm, String categoryId) {
return Result.success(contentService.pagePublished(pageForm, categoryId));
}
@At
@ApiOperation("内容详情")
@SaCheckPermission("spread.display")
public Result detailData(String id) {
try {
return Result.success(contentService.getContent(id));
} catch (RuntimeException e) {
return Result.error(e.getMessage());
}
}
@At
@ApiOperation("轮播内容")
@SaCheckPermission("spread.display")
public Result sliderData() {
return Result.success(contentService.sliderContent());
}
@At
@ApiOperation("增加浏览量")
@SaCheckPermission("spread.display")
public Result addView(String id) {
try {
contentService.addViewCount(id);
return Result.success();
} catch (RuntimeException e) {
return Result.error(e.getMessage());
}
}
}
@@ -0,0 +1,78 @@
package com.budwk.app.zhgh.spread.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import com.budwk.app.base.annotation.SLog;
import com.budwk.app.base.param.PageForm;
import com.budwk.app.base.result.Result;
import com.budwk.app.zhgh.spread.param.SpreadContentQuery;
import com.budwk.app.zhgh.spread.service.SpreadCategoryService;
import com.budwk.app.zhgh.spread.service.SpreadContentService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.nutz.aop.interceptor.ioc.TransAop;
import org.nutz.ioc.aop.Aop;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok;
@IocBean
@Ok("json:full")
@Api("风采墙-内容管理")
@At("/platform/spread/manage")
public class SpreadManageController {
@Inject
private SpreadCategoryService categoryService;
@Inject
private SpreadContentService contentService;
@At("")
@Ok("beetl:/platform/zhgh/spread/manage/index.html")
@SaCheckPermission("spread.manage")
public void index() {
}
@At
@ApiOperation("内容分页")
@SaCheckPermission("spread.manage")
public Result pageData(PageForm pageForm, SpreadContentQuery query) {
return Result.success(contentService.pageContent(pageForm, query));
}
@At
@ApiOperation("栏目树")
@SaCheckPermission("spread.manage")
public Result categoryTree() {
return Result.success(categoryService.categoryTree(false));
}
@At
@ApiOperation("删除内容")
@SaCheckPermission("spread.manage")
@SLog(tag = "风采墙-内容管理", msg = "删除内容:${args[0]}")
@Aop(TransAop.READ_COMMITTED)
public Result doDelete(String id) {
try {
contentService.deleteContent(id);
return Result.success();
} catch (RuntimeException e) {
return Result.error(e.getMessage());
}
}
@At
@ApiOperation("发布或撤回内容")
@SaCheckPermission("spread.manage")
@SLog(tag = "风采墙-内容管理", msg = "内容:${args[0]},发布状态:${args[1]}")
@Aop(TransAop.READ_COMMITTED)
public Result doPublish(String id, Integer status) {
try {
contentService.publishContent(id, status);
return Result.success();
} catch (RuntimeException e) {
return Result.error(e.getMessage());
}
}
}
@@ -0,0 +1,60 @@
package com.budwk.app.zhgh.spread.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import com.budwk.app.base.result.Result;
import com.budwk.app.zhgh.spread.param.SpreadStatisticsQuery;
import com.budwk.app.zhgh.spread.service.SpreadCategoryService;
import com.budwk.app.zhgh.spread.service.SpreadStatisticsService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok;
@IocBean
@Ok("json:full")
@Api("风采墙-统计分析")
@At("/platform/spread/statistics")
public class SpreadStatisticsController {
@Inject
private SpreadCategoryService categoryService;
@Inject
private SpreadStatisticsService statisticsService;
@At("")
@Ok("beetl:/platform/zhgh/spread/statistics/index.html")
@SaCheckPermission("spread.statistics")
public void index() {
}
@At
@ApiOperation("栏目树")
@SaCheckPermission("spread.statistics")
public Result categoryTree() {
return Result.success(categoryService.categoryTree(false));
}
@At
@ApiOperation("统计卡片")
@SaCheckPermission("spread.statistics")
public Result summary(SpreadStatisticsQuery query) {
return Result.success(statisticsService.summary(query));
}
@At
@ApiOperation("浏览量前十")
@SaCheckPermission("spread.statistics")
public Result top10(SpreadStatisticsQuery query) {
return Result.success(statisticsService.top10(query));
}
@At
@ApiOperation("栏目统计")
@SaCheckPermission("spread.statistics")
public Result categoryData(SpreadStatisticsQuery query) {
return Result.success(statisticsService.categoryStatistics(query));
}
}
@@ -0,0 +1,55 @@
package com.budwk.app.zhgh.spread.models;
import com.budwk.app.base.model.BaseModel;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.nutz.dao.entity.annotation.ColDefine;
import org.nutz.dao.entity.annotation.ColType;
import org.nutz.dao.entity.annotation.Column;
import org.nutz.dao.entity.annotation.Comment;
import org.nutz.dao.entity.annotation.Name;
import org.nutz.dao.entity.annotation.Table;
import org.nutz.dao.interceptor.annotation.PrevInsert;
@Data
@Table("spread_category")
@EqualsAndHashCode(callSuper = true)
public class SpreadCategory extends BaseModel {
@Column
@Name
@Comment("ID")
@ColDefine(type = ColType.VARCHAR, width = 32)
@PrevInsert(uu32 = true)
private String id;
@Column
@Comment("父栏目ID0表示顶级栏目")
@ColDefine(type = ColType.VARCHAR, width = 32)
private String parentId;
@Column
@Comment("栏目名称")
@ColDefine(type = ColType.VARCHAR, width = 100)
private String name;
@Column
@Comment("栏目编码")
@ColDefine(type = ColType.VARCHAR, width = 50)
private String code;
@Column
@Comment("排序")
@ColDefine(type = ColType.INT)
private Integer sortOrder;
@Column
@Comment("是否可见")
@ColDefine(type = ColType.INT)
private Integer visible;
@Column
@Comment("是否参与轮播")
@ColDefine(type = ColType.INT)
private Integer slider;
}
@@ -0,0 +1,99 @@
package com.budwk.app.zhgh.spread.models;
import com.budwk.app.base.model.BaseModel;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.nutz.dao.entity.annotation.ColDefine;
import org.nutz.dao.entity.annotation.ColType;
import org.nutz.dao.entity.annotation.Column;
import org.nutz.dao.entity.annotation.Comment;
import org.nutz.dao.entity.annotation.Name;
import org.nutz.dao.entity.annotation.Table;
import org.nutz.dao.interceptor.annotation.PrevInsert;
@Data
@Table("spread_content")
@EqualsAndHashCode(callSuper = true)
public class SpreadContent extends BaseModel {
@Column
@Name
@Comment("ID")
@ColDefine(type = ColType.VARCHAR, width = 32)
@PrevInsert(uu32 = true)
private String id;
@Column
@Comment("栏目ID")
@ColDefine(type = ColType.VARCHAR, width = 32)
private String categoryId;
@Column
@Comment("栏目名称")
@ColDefine(type = ColType.VARCHAR, width = 100)
private String categoryName;
@Column
@Comment("标题")
@ColDefine(type = ColType.VARCHAR, width = 300)
private String title;
@Column
@Comment("副标题")
@ColDefine(type = ColType.VARCHAR, width = 255)
private String subTitle;
@Column
@Comment("摘要")
@ColDefine(type = ColType.VARCHAR, width = 1000)
private String summary;
@Column
@Comment("正文")
@ColDefine(customType = "longtext")
private String contentBody;
@Column
@Comment("封面图")
@ColDefine(type = ColType.VARCHAR, width = 1000)
private String thumbUrl;
@Column
@Comment("轮播图片")
@ColDefine(customType = "longtext")
private String sliderImages;
@Column
@Comment("是否置顶")
@ColDefine(type = ColType.INT)
private Integer isTop;
@Column
@Comment("是否推荐")
@ColDefine(type = ColType.INT)
private Integer isRecommend;
@Column
@Comment("是否头条")
@ColDefine(type = ColType.INT)
private Integer isHeadline;
@Column
@Comment("浏览量")
@ColDefine(type = ColType.INT)
private Integer viewCount;
@Column
@Comment("排序")
@ColDefine(type = ColType.INT)
private Integer sortOrder;
@Column
@Comment("是否发布")
@ColDefine(type = ColType.INT)
private Integer isPublished;
@Column
@Comment("发布时间")
private Long publishedAt;
}
@@ -0,0 +1,12 @@
package com.budwk.app.zhgh.spread.param;
import lombok.Data;
@Data
public class SpreadContentQuery {
private String categoryId;
private String title;
private Integer isPublished;
private String beginTime;
private String endTime;
}
@@ -0,0 +1,11 @@
package com.budwk.app.zhgh.spread.param;
import lombok.Data;
@Data
public class SpreadStatisticsQuery {
private String categoryId;
private Integer isPublished;
private String beginTime;
private String endTime;
}
@@ -0,0 +1,22 @@
package com.budwk.app.zhgh.spread.service;
import com.budwk.app.base.service.BaseService;
import com.budwk.app.zhgh.spread.models.SpreadCategory;
import org.nutz.lang.util.NutMap;
import java.util.List;
public interface SpreadCategoryService extends BaseService<SpreadCategory> {
List<SpreadCategory> listCategories(boolean visibleOnly);
List<NutMap> categoryTree(boolean visibleOnly);
void saveCategory(SpreadCategory category);
void updateCategory(SpreadCategory category);
void deleteCategory(String id);
void setVisible(String id, Integer visible);
}
@@ -0,0 +1,31 @@
package com.budwk.app.zhgh.spread.service;
import com.budwk.app.base.page.Pagination;
import com.budwk.app.base.param.PageForm;
import com.budwk.app.base.service.BaseService;
import com.budwk.app.zhgh.spread.models.SpreadContent;
import com.budwk.app.zhgh.spread.param.SpreadContentQuery;
import org.nutz.lang.util.NutMap;
import java.util.List;
public interface SpreadContentService extends BaseService<SpreadContent> {
Pagination<NutMap> pageContent(PageForm pageForm, SpreadContentQuery query);
Pagination<NutMap> pagePublished(PageForm pageForm, String categoryId);
SpreadContent getContent(String id);
void saveContent(SpreadContent content);
void updateContent(SpreadContent content);
void deleteContent(String id);
void publishContent(String id, Integer status);
void addViewCount(String id);
List<NutMap> sliderContent();
}
@@ -0,0 +1,15 @@
package com.budwk.app.zhgh.spread.service;
import com.budwk.app.zhgh.spread.param.SpreadStatisticsQuery;
import org.nutz.lang.util.NutMap;
import java.util.List;
public interface SpreadStatisticsService {
NutMap summary(SpreadStatisticsQuery query);
List<NutMap> top10(SpreadStatisticsQuery query);
List<NutMap> categoryStatistics(SpreadStatisticsQuery query);
}
@@ -0,0 +1,180 @@
package com.budwk.app.zhgh.spread.service.impl;
import cn.hutool.core.util.StrUtil;
import com.budwk.app.base.service.impl.BaseServiceImpl;
import com.budwk.app.zhgh.spread.models.SpreadCategory;
import com.budwk.app.zhgh.spread.models.SpreadContent;
import com.budwk.app.zhgh.spread.service.SpreadCategoryService;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.util.NutMap;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@IocBean(args = {"refer:dao"})
public class SpreadCategoryServiceImpl extends BaseServiceImpl<SpreadCategory> implements SpreadCategoryService {
public SpreadCategoryServiceImpl(Dao dao) {
super(dao);
}
@Override
public List<SpreadCategory> listCategories(boolean visibleOnly) {
Cnd cnd = Cnd.where("delFlag", "=", false);
if (visibleOnly) {
cnd.and("visible", "=", 1);
}
cnd.asc("sortOrder").asc("createdAt");
return query(cnd);
}
@Override
public List<NutMap> categoryTree(boolean visibleOnly) {
List<SpreadCategory> categories = listCategories(visibleOnly);
Map<String, NutMap> nodeMap = new LinkedHashMap<>();
for (SpreadCategory category : categories) {
nodeMap.put(category.getId(), NutMap.NEW()
.addv("id", category.getId())
.addv("parentId", category.getParentId())
.addv("name", category.getName())
.addv("code", category.getCode())
.addv("sortOrder", category.getSortOrder())
.addv("visible", category.getVisible())
.addv("slider", category.getSlider())
.addv("children", new ArrayList<>()));
}
List<NutMap> roots = new ArrayList<>();
for (NutMap node : nodeMap.values()) {
String parentId = node.getString("parentId");
if ("0".equals(parentId) || !nodeMap.containsKey(parentId)) {
roots.add(node);
} else {
nodeMap.get(parentId).getList("children", NutMap.class).add(node);
}
}
return roots;
}
@Override
public void saveCategory(SpreadCategory category) {
validateCategory(category, null);
applyDefaults(category);
insert(category);
syncParentSlider(category);
}
@Override
public void updateCategory(SpreadCategory category) {
if (category == null || StrUtil.isBlank(category.getId())) {
throw new RuntimeException("请选择要编辑的栏目");
}
SpreadCategory dbCategory = fetch(category.getId());
if (dbCategory == null || Boolean.TRUE.equals(dbCategory.getDelFlag())) {
throw new RuntimeException("栏目不存在");
}
validateCategory(category, category.getId());
if (!dbCategory.getParentId().equals(category.getParentId())
&& count(Cnd.where("parentId", "=", category.getId()).and("delFlag", "=", false)) > 0) {
throw new RuntimeException("该栏目下存在子栏目,不能移动");
}
applyDefaults(category);
updateIgnoreNull(category);
syncParentSlider(category);
if ("0".equals(category.getParentId()) && Integer.valueOf(0).equals(category.getSlider())) {
SpreadCategory child = new SpreadCategory();
child.setSlider(0);
dao().update(SpreadCategory.class, org.nutz.dao.Chain.make("slider", 0),
Cnd.where("parentId", "=", category.getId()).and("delFlag", "=", false));
}
}
@Override
public void deleteCategory(String id) {
if (StrUtil.isBlank(id)) {
throw new RuntimeException("请选择要删除的栏目");
}
List<SpreadCategory> children = query(Cnd.where("parentId", "=", id).and("delFlag", "=", false));
List<String> ids = new ArrayList<>();
ids.add(id);
children.forEach(item -> ids.add(item.getId()));
if (dao().count(SpreadContent.class,
Cnd.where("categoryId", "in", ids).and("delFlag", "=", false)) > 0) {
throw new RuntimeException("栏目下存在内容,请先删除相关内容");
}
dao().clear(SpreadCategory.class, Cnd.where("id", "in", ids));
}
@Override
public void setVisible(String id, Integer visible) {
if (StrUtil.isBlank(id) || (visible == null || (visible != 0 && visible != 1))) {
throw new RuntimeException("栏目或显示状态不正确");
}
dao().update(SpreadCategory.class, org.nutz.dao.Chain.make("visible", visible),
Cnd.where("id", "=", id).and("delFlag", "=", false));
if (visible == 0) {
dao().update(SpreadCategory.class, org.nutz.dao.Chain.make("visible", 0),
Cnd.where("parentId", "=", id).and("delFlag", "=", false));
}
}
private void validateCategory(SpreadCategory category, String excludeId) {
if (category == null || StrUtil.isBlank(category.getName())) {
throw new RuntimeException("栏目名称不能为空");
}
if (StrUtil.isBlank(category.getCode())) {
throw new RuntimeException("栏目编码不能为空");
}
category.setName(category.getName().trim());
category.setCode(category.getCode().trim());
category.setParentId(StrUtil.blankToDefault(category.getParentId(), "0"));
if (category.getId() != null && category.getId().equals(category.getParentId())) {
throw new RuntimeException("上级栏目不能选择自身");
}
if (!"0".equals(category.getParentId())) {
SpreadCategory parent = fetch(category.getParentId());
if (parent == null || Boolean.TRUE.equals(parent.getDelFlag())) {
throw new RuntimeException("上级栏目不存在");
}
if (!"0".equals(parent.getParentId())) {
throw new RuntimeException("风采墙栏目最多支持两级");
}
}
Cnd nameCnd = Cnd.where("name", "=", category.getName())
.and("parentId", "=", category.getParentId())
.and("delFlag", "=", false);
Cnd codeCnd = Cnd.where("code", "=", category.getCode()).and("delFlag", "=", false);
if (StrUtil.isNotBlank(excludeId)) {
nameCnd.and("id", "!=", excludeId);
codeCnd.and("id", "!=", excludeId);
}
if (count(nameCnd) > 0) {
throw new RuntimeException("同级栏目名称已存在");
}
if (count(codeCnd) > 0) {
throw new RuntimeException("栏目编码已存在");
}
}
private void applyDefaults(SpreadCategory category) {
if (category.getSortOrder() == null) {
category.setSortOrder(255);
}
if (category.getVisible() == null) {
category.setVisible(1);
}
if (category.getSlider() == null) {
category.setSlider(0);
}
}
private void syncParentSlider(SpreadCategory category) {
if (!"0".equals(category.getParentId()) && Integer.valueOf(1).equals(category.getSlider())) {
dao().update(SpreadCategory.class, org.nutz.dao.Chain.make("slider", 1),
Cnd.where("id", "=", category.getParentId()).and("delFlag", "=", false));
}
}
}
@@ -0,0 +1,234 @@
package com.budwk.app.zhgh.spread.service.impl;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.budwk.app.base.page.Pagination;
import com.budwk.app.base.param.PageForm;
import com.budwk.app.base.service.impl.BaseServiceImpl;
import com.budwk.app.zhgh.spread.models.SpreadCategory;
import com.budwk.app.zhgh.spread.models.SpreadContent;
import com.budwk.app.zhgh.spread.param.SpreadContentQuery;
import com.budwk.app.zhgh.spread.service.SpreadContentService;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.dao.Sqls;
import org.nutz.dao.sql.Sql;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.util.NutMap;
import java.util.ArrayList;
import java.util.List;
@IocBean(args = {"refer:dao"})
public class SpreadContentServiceImpl extends BaseServiceImpl<SpreadContent> implements SpreadContentService {
public SpreadContentServiceImpl(Dao dao) {
super(dao);
}
@Override
public Pagination<NutMap> pageContent(PageForm pageForm, SpreadContentQuery query) {
Cnd cnd = buildCondition(query);
Sql countSql = Sqls.create("""
SELECT COUNT(1)
FROM spread_content c
$condition
""");
countSql.setCondition(cnd);
countSql.setCallback(Sqls.callback.integer());
dao().execute(countSql);
Sql listSql = Sqls.create("""
SELECT c.*
FROM spread_content c
$condition
ORDER BY c.isTop DESC, c.sortOrder ASC, c.createdAt DESC
""");
listSql.setCondition(cnd);
listSql.setPager(dao().createPager(pageForm.getPageNumber(), pageForm.getPageSize()));
listSql.setCallback(Sqls.callback.maps());
dao().execute(listSql);
return new Pagination<>(pageForm.getPageNumber(), pageForm.getPageSize(),
countSql.getInt(), listSql.getList(NutMap.class));
}
@Override
public Pagination<NutMap> pagePublished(PageForm pageForm, String categoryId) {
SpreadContentQuery query = new SpreadContentQuery();
query.setCategoryId(categoryId);
query.setIsPublished(1);
Cnd cnd = buildCondition(query);
Sql countSql = Sqls.create("SELECT COUNT(1) FROM spread_content c $condition");
countSql.setCondition(cnd);
countSql.setCallback(Sqls.callback.integer());
dao().execute(countSql);
Sql listSql = Sqls.create("""
SELECT c.*
FROM spread_content c
$condition
ORDER BY c.isTop DESC, c.publishedAt DESC, c.sortOrder ASC, c.createdAt DESC
""");
listSql.setCondition(cnd);
listSql.setPager(dao().createPager(pageForm.getPageNumber(), pageForm.getPageSize()));
listSql.setCallback(Sqls.callback.maps());
dao().execute(listSql);
return new Pagination<>(pageForm.getPageNumber(), pageForm.getPageSize(),
countSql.getInt(), listSql.getList(NutMap.class));
}
@Override
public SpreadContent getContent(String id) {
if (StrUtil.isBlank(id)) {
throw new RuntimeException("请选择内容");
}
SpreadContent content = fetch(Cnd.where("id", "=", id).and("delFlag", "=", false));
if (content == null) {
throw new RuntimeException("内容不存在");
}
return content;
}
@Override
public void saveContent(SpreadContent content) {
validateContent(content);
applyDefaults(content);
if (Integer.valueOf(1).equals(content.getIsPublished())) {
content.setPublishedAt(System.currentTimeMillis());
}
insert(content);
}
@Override
public void updateContent(SpreadContent content) {
if (content == null || StrUtil.isBlank(content.getId())) {
throw new RuntimeException("请选择要编辑的内容");
}
SpreadContent dbContent = getContent(content.getId());
validateContent(content);
applyDefaults(content);
if (Integer.valueOf(1).equals(content.getIsPublished()) && !Integer.valueOf(1).equals(dbContent.getIsPublished())) {
content.setPublishedAt(System.currentTimeMillis());
}
updateIgnoreNull(content);
}
@Override
public void deleteContent(String id) {
getContent(id);
dao().clear(SpreadContent.class, Cnd.where("id", "=", id));
}
@Override
public void publishContent(String id, Integer status) {
getContent(id);
if (status == null || (status != 0 && status != 1)) {
throw new RuntimeException("发布状态不正确");
}
org.nutz.dao.Chain chain = org.nutz.dao.Chain.make("isPublished", status);
if (status == 1) {
chain.add("publishedAt", System.currentTimeMillis());
}
dao().update(SpreadContent.class, chain, Cnd.where("id", "=", id).and("delFlag", "=", false));
}
@Override
public void addViewCount(String id) {
getContent(id);
Sql sql = Sqls.create("""
UPDATE spread_content
SET viewCount = IFNULL(viewCount, 0) + 1,
updatedAt = @updatedAt
WHERE id = @id AND delFlag = 0
""");
sql.params().set("id", id);
sql.params().set("updatedAt", System.currentTimeMillis());
dao().execute(sql);
}
@Override
public List<NutMap> sliderContent() {
Sql sql = Sqls.create("""
SELECT c.id, c.title, c.summary, c.thumbUrl, c.sliderImages, c.categoryId, c.categoryName
FROM spread_content c
INNER JOIN spread_category child ON child.id = c.categoryId
LEFT JOIN spread_category parent ON parent.id = child.parentId
WHERE c.delFlag = 0
AND c.isPublished = 1
AND child.delFlag = 0
AND child.visible = 1
AND child.slider = 1
AND (child.parentId = '0' OR (parent.delFlag = 0 AND parent.visible = 1 AND parent.slider = 1))
ORDER BY c.isTop DESC, c.publishedAt DESC, c.createdAt DESC
LIMIT 10
""");
sql.setCallback(Sqls.callback.maps());
dao().execute(sql);
return sql.getList(NutMap.class);
}
private Cnd buildCondition(SpreadContentQuery query) {
Cnd cnd = Cnd.where("c.delFlag", "=", false);
if (query == null) {
return cnd;
}
if (StrUtil.isNotBlank(query.getCategoryId())) {
List<String> categoryIds = new ArrayList<>();
categoryIds.add(query.getCategoryId());
List<SpreadCategory> children = dao().query(SpreadCategory.class,
Cnd.where("parentId", "=", query.getCategoryId()).and("delFlag", "=", false));
children.forEach(item -> categoryIds.add(item.getId()));
cnd.and("c.categoryId", "in", categoryIds);
}
cnd.and(Cnd.likeEX("c.title", query.getTitle()));
cnd.andEX("c.isPublished", "=", query.getIsPublished());
if (StrUtil.isNotBlank(query.getBeginTime())) {
cnd.and("c.createdAt", ">=", DateUtil.parse(query.getBeginTime()).getTime());
}
if (StrUtil.isNotBlank(query.getEndTime())) {
cnd.and("c.createdAt", "<=", DateUtil.parse(query.getEndTime()).getTime());
}
return cnd;
}
private void validateContent(SpreadContent content) {
if (content == null || StrUtil.isBlank(content.getCategoryId())) {
throw new RuntimeException("请选择栏目");
}
SpreadCategory category = dao().fetch(SpreadCategory.class,
Cnd.where("id", "=", content.getCategoryId()).and("delFlag", "=", false));
if (category == null) {
throw new RuntimeException("栏目不存在");
}
if (dao().count(SpreadCategory.class,
Cnd.where("parentId", "=", category.getId()).and("delFlag", "=", false)) > 0) {
throw new RuntimeException("内容只能发布到末级栏目");
}
if (StrUtil.isBlank(content.getTitle())) {
throw new RuntimeException("标题不能为空");
}
content.setTitle(content.getTitle().trim());
content.setCategoryName(category.getName());
}
private void applyDefaults(SpreadContent content) {
if (content.getIsTop() == null) {
content.setIsTop(0);
}
if (content.getIsRecommend() == null) {
content.setIsRecommend(0);
}
if (content.getIsHeadline() == null) {
content.setIsHeadline(0);
}
if (content.getViewCount() == null) {
content.setViewCount(0);
}
if (content.getSortOrder() == null) {
content.setSortOrder(255);
}
if (content.getIsPublished() == null) {
content.setIsPublished(0);
}
}
}
@@ -0,0 +1,113 @@
package com.budwk.app.zhgh.spread.service.impl;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.budwk.app.zhgh.spread.param.SpreadStatisticsQuery;
import com.budwk.app.zhgh.spread.service.SpreadStatisticsService;
import org.nutz.dao.Dao;
import org.nutz.dao.Sqls;
import org.nutz.dao.sql.Sql;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.util.NutMap;
import java.util.List;
@IocBean
public class SpreadStatisticsServiceImpl implements SpreadStatisticsService {
@Inject
private Dao dao;
@Override
public NutMap summary(SpreadStatisticsQuery query) {
String condition = buildContentCondition(query, "c");
Sql sql = Sqls.create("""
SELECT
(SELECT COUNT(1) FROM spread_category cg WHERE cg.delFlag = 0) AS categoryCount,
COUNT(1) AS contentCount,
IFNULL(SUM(CASE WHEN c.isPublished = 1 THEN 1 ELSE 0 END), 0) AS publishedCount,
IFNULL(SUM(c.viewCount), 0) AS viewCount,
IFNULL(ROUND(AVG(c.viewCount)), 0) AS avgViewCount
FROM spread_content c
WHERE c.delFlag = 0
$condition
""");
sql.setVar("condition", condition);
setParams(sql, query);
sql.setCallback(Sqls.callback.map());
dao.execute(sql);
NutMap result = sql.getObject(NutMap.class);
return result == null ? NutMap.NEW() : result;
}
@Override
public List<NutMap> top10(SpreadStatisticsQuery query) {
Sql sql = Sqls.create("""
SELECT c.id, c.title, c.categoryName, c.viewCount, c.isPublished, c.publishedAt
FROM spread_content c
WHERE c.delFlag = 0
$condition
ORDER BY c.viewCount DESC, c.updatedAt DESC
LIMIT 10
""");
sql.setVar("condition", buildContentCondition(query, "c"));
setParams(sql, query);
sql.setCallback(Sqls.callback.maps());
dao.execute(sql);
return sql.getList(NutMap.class);
}
@Override
public List<NutMap> categoryStatistics(SpreadStatisticsQuery query) {
Sql sql = Sqls.create("""
SELECT c.categoryId, c.categoryName, COUNT(1) AS contentCount,
IFNULL(SUM(c.viewCount), 0) AS viewCount
FROM spread_content c
WHERE c.delFlag = 0
$condition
GROUP BY c.categoryId, c.categoryName
ORDER BY viewCount DESC, contentCount DESC
""");
sql.setVar("condition", buildContentCondition(query, "c"));
setParams(sql, query);
sql.setCallback(Sqls.callback.maps());
dao.execute(sql);
return sql.getList(NutMap.class);
}
private String buildContentCondition(SpreadStatisticsQuery query, String alias) {
if (query == null) {
return "";
}
StringBuilder condition = new StringBuilder();
if (StrUtil.isNotBlank(query.getCategoryId())) {
condition.append(" AND ").append(alias)
.append(".categoryId IN (SELECT id FROM spread_category WHERE id = @categoryId OR parentId = @categoryId)");
}
if (query.getIsPublished() != null) {
condition.append(" AND ").append(alias).append(".isPublished = @isPublished");
}
if (StrUtil.isNotBlank(query.getBeginTime())) {
condition.append(" AND ").append(alias).append(".createdAt >= @beginAt");
}
if (StrUtil.isNotBlank(query.getEndTime())) {
condition.append(" AND ").append(alias).append(".createdAt <= @endAt");
}
return condition.toString();
}
private void setParams(Sql sql, SpreadStatisticsQuery query) {
if (query == null) {
return;
}
sql.params().set("categoryId", query.getCategoryId());
sql.params().set("isPublished", query.getIsPublished());
if (StrUtil.isNotBlank(query.getBeginTime())) {
sql.params().set("beginAt", DateUtil.parse(query.getBeginTime()).getTime());
}
if (StrUtil.isNotBlank(query.getEndTime())) {
sql.params().set("endAt", DateUtil.parse(query.getEndTime()).getTime());
}
}
}