diff --git a/ant-design-vue-jeecg/src/config/router.config.js b/ant-design-vue-jeecg/src/config/router.config.js index 557ce7e..38126ce 100644 --- a/ant-design-vue-jeecg/src/config/router.config.js +++ b/ant-design-vue-jeecg/src/config/router.config.js @@ -553,5 +553,21 @@ export const constantRouterMap = [ // component: () => import(/* webpackChunkName: "fail" */ '@/views/seknowgroup/SeKnowAtlasList'), }, + //cms首页,免登录,单独访问页面 + // #/protal/home + //需要在新窗口打开的页面路径 + { + path: '/cms/home',//这里是你需要设置新窗口打开的页面的路径 + component: () => import('@/views/cms/home'), + }, + { + path: '/cms/major',//这里是你需要设置新窗口打开的页面的路径 + component: () => import('@/views/cms/pages/Major/MajorView'), + }, + { + path: '/cms/detail',//这里是你需要设置新窗口打开的页面的路径 + component: () => import('@/views/cms/pages/Detail/DetailView'), + }, + ] diff --git a/ant-design-vue-jeecg/src/permission.js b/ant-design-vue-jeecg/src/permission.js index f9b494a..d9de25c 100644 --- a/ant-design-vue-jeecg/src/permission.js +++ b/ant-design-vue-jeecg/src/permission.js @@ -26,6 +26,9 @@ const whiteList = [ '/user/register', '/user/register-result', '/user/alteration', + '/cms/home', + '/cms/major', + '/cms/detail', ] // no redirect whitelist router.beforeEach((to, from, next) => { diff --git a/ant-design-vue-jeecg/src/views/cms/admin/CmsArticleList.vue b/ant-design-vue-jeecg/src/views/cms/admin/CmsArticleList.vue new file mode 100644 index 0000000..f6831d5 --- /dev/null +++ b/ant-design-vue-jeecg/src/views/cms/admin/CmsArticleList.vue @@ -0,0 +1,209 @@ + + + + \ No newline at end of file diff --git a/ant-design-vue-jeecg/src/views/cms/admin/CmsColumnList.vue b/ant-design-vue-jeecg/src/views/cms/admin/CmsColumnList.vue new file mode 100644 index 0000000..fc66e84 --- /dev/null +++ b/ant-design-vue-jeecg/src/views/cms/admin/CmsColumnList.vue @@ -0,0 +1,379 @@ + + + + \ No newline at end of file diff --git a/ant-design-vue-jeecg/src/views/cms/admin/modules/CmsArticleForm.vue b/ant-design-vue-jeecg/src/views/cms/admin/modules/CmsArticleForm.vue new file mode 100644 index 0000000..2edf646 --- /dev/null +++ b/ant-design-vue-jeecg/src/views/cms/admin/modules/CmsArticleForm.vue @@ -0,0 +1,132 @@ + + + \ No newline at end of file diff --git a/ant-design-vue-jeecg/src/views/cms/admin/modules/CmsArticleModal.vue b/ant-design-vue-jeecg/src/views/cms/admin/modules/CmsArticleModal.vue new file mode 100644 index 0000000..73ec834 --- /dev/null +++ b/ant-design-vue-jeecg/src/views/cms/admin/modules/CmsArticleModal.vue @@ -0,0 +1,60 @@ + + + \ No newline at end of file diff --git a/ant-design-vue-jeecg/src/views/cms/admin/modules/CmsArticleModal__Style#Drawer.vue b/ant-design-vue-jeecg/src/views/cms/admin/modules/CmsArticleModal__Style#Drawer.vue new file mode 100644 index 0000000..de0be2a --- /dev/null +++ b/ant-design-vue-jeecg/src/views/cms/admin/modules/CmsArticleModal__Style#Drawer.vue @@ -0,0 +1,84 @@ + + + + + \ No newline at end of file diff --git a/ant-design-vue-jeecg/src/views/cms/admin/modules/CmsColumnModal.vue b/ant-design-vue-jeecg/src/views/cms/admin/modules/CmsColumnModal.vue new file mode 100644 index 0000000..d8705ce --- /dev/null +++ b/ant-design-vue-jeecg/src/views/cms/admin/modules/CmsColumnModal.vue @@ -0,0 +1,165 @@ + + + \ No newline at end of file diff --git a/ant-design-vue-jeecg/src/views/cms/assets/Group01.png b/ant-design-vue-jeecg/src/views/cms/assets/Group01.png new file mode 100644 index 0000000..787f8e1 Binary files /dev/null and b/ant-design-vue-jeecg/src/views/cms/assets/Group01.png differ diff --git a/ant-design-vue-jeecg/src/views/cms/assets/Group02.png b/ant-design-vue-jeecg/src/views/cms/assets/Group02.png new file mode 100644 index 0000000..4bb4ced Binary files /dev/null and b/ant-design-vue-jeecg/src/views/cms/assets/Group02.png differ diff --git a/ant-design-vue-jeecg/src/views/cms/assets/Group03.png b/ant-design-vue-jeecg/src/views/cms/assets/Group03.png new file mode 100644 index 0000000..21e71bc Binary files /dev/null and b/ant-design-vue-jeecg/src/views/cms/assets/Group03.png differ diff --git a/ant-design-vue-jeecg/src/views/cms/assets/Group04.png b/ant-design-vue-jeecg/src/views/cms/assets/Group04.png new file mode 100644 index 0000000..92d030a Binary files /dev/null and b/ant-design-vue-jeecg/src/views/cms/assets/Group04.png differ diff --git a/ant-design-vue-jeecg/src/views/cms/assets/bg02.png b/ant-design-vue-jeecg/src/views/cms/assets/bg02.png new file mode 100644 index 0000000..292a6ab Binary files /dev/null and b/ant-design-vue-jeecg/src/views/cms/assets/bg02.png differ diff --git a/ant-design-vue-jeecg/src/views/cms/assets/logo.png b/ant-design-vue-jeecg/src/views/cms/assets/logo.png new file mode 100644 index 0000000..2455855 Binary files /dev/null and b/ant-design-vue-jeecg/src/views/cms/assets/logo.png differ diff --git a/ant-design-vue-jeecg/src/views/cms/assets/logo5.png b/ant-design-vue-jeecg/src/views/cms/assets/logo5.png new file mode 100644 index 0000000..82ea632 Binary files /dev/null and b/ant-design-vue-jeecg/src/views/cms/assets/logo5.png differ diff --git a/ant-design-vue-jeecg/src/views/cms/assets/reset.css b/ant-design-vue-jeecg/src/views/cms/assets/reset.css new file mode 100644 index 0000000..dd2ca75 --- /dev/null +++ b/ant-design-vue-jeecg/src/views/cms/assets/reset.css @@ -0,0 +1,64 @@ +* { + margin: 0; + padding: 0 +} + +em, +i { + font-style: normal +} + +li { + list-style: none +} + +img { + border: 0; + vertical-align: middle +} + +button { + cursor: pointer +} + +a { + color: #666; + text-decoration: none +} + +a:hover { + color: #c81623 +} + +button, +input { + font-family: Microsoft YaHei, tahoma, arial, Hiragino Sans GB, \\5b8b\4f53, sans-serif +} + +body { + -webkit-font-smoothing: antialiased; + background-color: #fff; + font: 12px/1.5 Microsoft YaHei, tahoma, arial, Hiragino Sans GB, \\5b8b\4f53, sans-serif; + color: #666 +} + +.hide, +.none { + display: none +} + +.clearfix:after { + visibility: hidden; + clear: both; + display: block; + content: "."; + height: 0 +} + +.clearfix { + *zoom: 1 +} +.d-flex{ + display: flex; + justify-content: space-between;align-items: center; +} \ No newline at end of file diff --git a/ant-design-vue-jeecg/src/views/cms/components/FooterView.vue b/ant-design-vue-jeecg/src/views/cms/components/FooterView.vue new file mode 100644 index 0000000..a7cc602 --- /dev/null +++ b/ant-design-vue-jeecg/src/views/cms/components/FooterView.vue @@ -0,0 +1,53 @@ + + + + + + diff --git a/ant-design-vue-jeecg/src/views/cms/components/HeaderView.vue b/ant-design-vue-jeecg/src/views/cms/components/HeaderView.vue new file mode 100644 index 0000000..ddcb2bf --- /dev/null +++ b/ant-design-vue-jeecg/src/views/cms/components/HeaderView.vue @@ -0,0 +1,108 @@ + + + + + + diff --git a/ant-design-vue-jeecg/src/views/cms/home.vue b/ant-design-vue-jeecg/src/views/cms/home.vue new file mode 100644 index 0000000..61e20cf --- /dev/null +++ b/ant-design-vue-jeecg/src/views/cms/home.vue @@ -0,0 +1,195 @@ + + + + + \ No newline at end of file diff --git a/ant-design-vue-jeecg/src/views/cms/pages/Detail/DetailView.vue b/ant-design-vue-jeecg/src/views/cms/pages/Detail/DetailView.vue new file mode 100644 index 0000000..2701a8c --- /dev/null +++ b/ant-design-vue-jeecg/src/views/cms/pages/Detail/DetailView.vue @@ -0,0 +1,268 @@ + + + + + \ No newline at end of file diff --git a/ant-design-vue-jeecg/src/views/cms/pages/Major/MajorView.vue b/ant-design-vue-jeecg/src/views/cms/pages/Major/MajorView.vue new file mode 100644 index 0000000..f088fdb --- /dev/null +++ b/ant-design-vue-jeecg/src/views/cms/pages/Major/MajorView.vue @@ -0,0 +1,290 @@ + + + + + \ No newline at end of file diff --git a/jeecg-boot/jeecg-boot-module-cms/pom.xml b/jeecg-boot/jeecg-boot-module-cms/pom.xml new file mode 100644 index 0000000..3c4d0f6 --- /dev/null +++ b/jeecg-boot/jeecg-boot-module-cms/pom.xml @@ -0,0 +1,41 @@ + + + + jeecg-boot-parent + org.jeecgframework.boot + 2.4.5 + + 4.0.0 + + jeecg-boot-module-cms + + + + org.jeecgframework.boot + jeecg-boot-base-core + + + org.jeecgframework.boot + jeecg-boot-base-core + + + us.codecraft + webmagic-core + 0.7.3 + + + us.codecraft + webmagic-extension + 0.7.3 + + + + + + + + + + diff --git a/jeecg-boot/jeecg-boot-module-cms/src/main/java/org/jeecg/modules/cms/admin/controller/CmsArticleController.java b/jeecg-boot/jeecg-boot-module-cms/src/main/java/org/jeecg/modules/cms/admin/controller/CmsArticleController.java new file mode 100644 index 0000000..9ecc960 --- /dev/null +++ b/jeecg-boot/jeecg-boot-module-cms/src/main/java/org/jeecg/modules/cms/admin/controller/CmsArticleController.java @@ -0,0 +1,190 @@ +package org.jeecg.modules.cms.admin.controller; + + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.apache.shiro.SecurityUtils; +import org.jeecg.common.api.vo.Result; +import org.jeecg.common.aspect.annotation.AutoLog; +import org.jeecg.common.system.base.controller.JeecgController; +import org.jeecg.common.system.query.QueryGenerator; +import org.jeecg.common.system.vo.LoginUser; +import org.jeecg.modules.cms.admin.entity.CmsArticle; +import org.jeecg.modules.cms.admin.entity.CmsColumn; +import org.jeecg.modules.cms.admin.service.ICmsArticleService; +import org.jeecg.modules.cms.admin.service.ICmsColumnService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.servlet.ModelAndView; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.validation.constraints.Null; +import java.time.LocalDateTime; +import java.util.Arrays; +import java.util.Date; + +/** + * @Description: 文章管理 + * @Author: jeecg-boot + * @Date: 2023-03-27 + * @Version: V1.0 + */ +@Api(tags = "文章管理") +@RestController +@RequestMapping("/cms/cmsArticle") +@Slf4j +public class CmsArticleController extends JeecgController { + @Autowired + private ICmsArticleService cmsArticleService; + + @Autowired + private ICmsColumnService cmsColumnService; + + /** + * 分页列表查询 + * + * @param cmsArticle + * @param pageNo + * @param pageSize + * @param req + * @return + */ +// @AutoLog(value = "文章管理-分页列表查询") + @ApiOperation(value = "文章管理-分页列表查询", notes = "文章管理-分页列表查询") + @GetMapping(value = "/list") + public Result queryPageList(CmsArticle cmsArticle, + @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, + @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, + HttpServletRequest req) { + QueryWrapper queryWrapper = QueryGenerator.initQueryWrapper(cmsArticle, req.getParameterMap()); + Page page = new Page(pageNo, pageSize); + IPage pageList = cmsArticleService.page(page, queryWrapper); + return Result.OK(pageList); + } + + /** + * 添加 + * + * @param cmsArticle + * @return + */ +// @AutoLog(value = "文章管理-添加") + @ApiOperation(value = "文章管理-添加", notes = "文章管理-添加") + @PostMapping(value = "/add") + public Result add(@RequestBody CmsArticle cmsArticle) { + LoginUser principal = (LoginUser) SecurityUtils.getSubject().getPrincipal(); + cmsArticle.setCreateBy(principal.getUsername()); + CmsColumn cmsColumn = cmsColumnService.getById(cmsArticle.getColumnId()); + cmsArticle.setColumnName(cmsColumn.getName()); + if (StringUtils.equals("1", cmsArticle.getStatus())) { + cmsArticle.setPublishTime(new Date()); + } + cmsArticleService.save(cmsArticle); + return Result.OK("添加成功!"); + } + + @ApiOperation(value = "文章管理-发布/取消发布", notes = "文章管理-发布/取消发布") + @PostMapping(value = "/operationStatus") + public Result operationStatus(@RequestBody CmsArticle cmsArticle) { + if (StringUtils.equals("1", cmsArticle.getStatus())) { + cmsArticle.setPublishTime(new Date()); + } + + cmsArticleService.updateById(cmsArticle); + return Result.OK("操作成功!"); + } + + /** + * 编辑 + * + * @param cmsArticle + * @return + */ +// @AutoLog(value = "文章管理-编辑") + @ApiOperation(value = "文章管理-编辑", notes = "文章管理-编辑") + @PutMapping(value = "/edit") + public Result edit(@RequestBody CmsArticle cmsArticle) { + if (StringUtils.equals("1", cmsArticle.getStatus())) { + cmsArticle.setPublishTime(new Date()); + } else { + cmsArticle.setPublishTime(null); + } + cmsArticleService.updateById(cmsArticle); + return Result.OK("编辑成功!"); + } + + /** + * 通过id删除 + * + * @param id + * @return + */ +// @AutoLog(value = "文章管理-通过id删除") + @ApiOperation(value = "文章管理-通过id删除", notes = "文章管理-通过id删除") + @DeleteMapping(value = "/delete") + public Result delete(@RequestParam(name = "id", required = true) String id) { + cmsArticleService.removeById(id); + return Result.OK("删除成功!"); + } + + /** + * 批量删除 + * + * @param ids + * @return + */ +// @AutoLog(value = "文章管理-批量删除") + @ApiOperation(value = "文章管理-批量删除", notes = "文章管理-批量删除") + @DeleteMapping(value = "/deleteBatch") + public Result deleteBatch(@RequestParam(name = "ids", required = true) String ids) { + this.cmsArticleService.removeByIds(Arrays.asList(ids.split(","))); + return Result.OK("批量删除成功!"); + } + + /** + * 通过id查询 + * + * @param id + * @return + */ +// @AutoLog(value = "文章管理-通过id查询") + @ApiOperation(value = "文章管理-通过id查询", notes = "文章管理-通过id查询") + @GetMapping(value = "/queryById") + public Result queryById(@RequestParam(name = "id", required = true) String id) { + CmsArticle cmsArticle = cmsArticleService.getById(id); + if (cmsArticle == null) { + return Result.error("未找到对应数据"); + } + return Result.OK(cmsArticle); + } + + /** + * 导出excel + * + * @param request + * @param cmsArticle + */ + @RequestMapping(value = "/exportXls") + public ModelAndView exportXls(HttpServletRequest request, CmsArticle cmsArticle) { + return super.exportXls(request, cmsArticle, CmsArticle.class, "文章管理"); + } + + /** + * 通过excel导入数据 + * + * @param request + * @param response + * @return + */ + @RequestMapping(value = "/importExcel", method = RequestMethod.POST) + public Result importExcel(HttpServletRequest request, HttpServletResponse response) { + return super.importExcel(request, response, CmsArticle.class); + } + +} diff --git a/jeecg-boot/jeecg-boot-module-cms/src/main/java/org/jeecg/modules/cms/admin/controller/CmsColumnController.java b/jeecg-boot/jeecg-boot-module-cms/src/main/java/org/jeecg/modules/cms/admin/controller/CmsColumnController.java new file mode 100644 index 0000000..c871553 --- /dev/null +++ b/jeecg-boot/jeecg-boot-module-cms/src/main/java/org/jeecg/modules/cms/admin/controller/CmsColumnController.java @@ -0,0 +1,260 @@ +package org.jeecg.modules.cms.admin.controller; + +import cn.hutool.core.lang.tree.Tree; +import cn.hutool.core.lang.tree.TreeNodeConfig; +import cn.hutool.core.lang.tree.TreeUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.apache.shiro.SecurityUtils; +import org.jeecg.common.api.vo.Result; +import org.jeecg.common.aspect.annotation.AutoLog; +import org.jeecg.common.exception.JeecgBootException; +import org.jeecg.common.system.base.controller.JeecgController; +import org.jeecg.common.system.query.QueryGenerator; +import org.jeecg.common.system.vo.LoginUser; +import org.jeecg.common.util.oConvertUtils; +import org.jeecg.modules.cms.admin.entity.CmsColumn; +import org.jeecg.modules.cms.admin.service.ICmsColumnService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.servlet.ModelAndView; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +/** + * @Description: 文章栏目 + * @Author: jeecg-boot + * @Date: 2023-03-27 + * @Version: V1.0 + */ +@Api(tags = "文章栏目") +@RestController +@RequestMapping("/cms/cmsColumn") +@Slf4j +public class CmsColumnController extends JeecgController { + @Autowired + private ICmsColumnService cmsColumnService; + + @ApiOperation(value = "文章栏目-获取栏目树型列表", notes = "文章栏目-获取栏目树型列表") + @GetMapping(value = "/getColumnTree") + public Result getColumnTree(HttpServletRequest req) { + //1.配置树节点信息,指定key,可直接使用默认的key + //2.查询数据 + List list = cmsColumnService.list(new LambdaQueryWrapper().orderByAsc(CmsColumn::getSort)); + //3.转为树结构,其中rootId参数代表根节点的父级id值 + TreeNodeConfig treeNodeConfig = new TreeNodeConfig(); + treeNodeConfig.setParentIdKey("pid"); + //转换器 + List> treeNodes = TreeUtil.build(list, "0", treeNodeConfig, + (treeNode, tree) -> { + tree.setId(treeNode.getId().toString()); + tree.setName(treeNode.getName()); + // 扩展属性 ... + tree.putExtra("isShow", treeNode.getIsShow()); + tree.putExtra("pid", treeNode.getPid()); + }); + return Result.OK(treeNodes); + } + + /** + * 分页列表查询 + * + * @param cmsColumn + * @param pageNo + * @param pageSize + * @param req + * @return + */ +// @AutoLog(value = "文章栏目-分页列表查询") + @ApiOperation(value = "文章栏目-分页列表查询", notes = "文章栏目-分页列表查询") + @GetMapping(value = "/rootList") + public Result queryPageList(CmsColumn cmsColumn, + @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, + @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, + HttpServletRequest req) { + String hasQuery = req.getParameter("hasQuery"); + if (hasQuery != null && "true".equals(hasQuery)) { + QueryWrapper queryWrapper = QueryGenerator.initQueryWrapper(cmsColumn, req.getParameterMap()); + List list = cmsColumnService.queryTreeListNoPage(queryWrapper); + IPage pageList = new Page<>(1, 10, list.size()); + pageList.setRecords(list); + List records = pageList.getRecords(); + Collections.sort(records, Comparator.comparingInt(CmsColumn::getSort)); + return Result.OK(pageList); + } else { + String parentId = cmsColumn.getPid(); + if (oConvertUtils.isEmpty(parentId)) { + parentId = "0"; + } + cmsColumn.setPid(null); + QueryWrapper queryWrapper = QueryGenerator.initQueryWrapper(cmsColumn, req.getParameterMap()); + // 使用 eq 防止模糊查询 + queryWrapper.eq("pid", parentId); + queryWrapper.last("order by sort"); + Page page = new Page(pageNo, pageSize); + IPage pageList = cmsColumnService.page(page, queryWrapper); + List records = pageList.getRecords(); +// records.sort(Comparator.comparing(CmsColumn::getSort)); + Collections.sort(records, Comparator.comparingInt(CmsColumn::getSort)); + + return Result.OK(pageList); + } + } + + /** + * 获取子数据 + * + * @param cmsColumn + * @param req + * @return + */ +// @AutoLog(value = "文章栏目-获取子数据") + @ApiOperation(value = "文章栏目-获取子数据", notes = "文章栏目-获取子数据") + @GetMapping(value = "/childList") + public Result queryPageList(CmsColumn cmsColumn, HttpServletRequest req) { + QueryWrapper queryWrapper = QueryGenerator.initQueryWrapper(cmsColumn, req.getParameterMap()); + List list = cmsColumnService.list(queryWrapper); + IPage pageList = new Page<>(1, 10, list.size()); + pageList.setRecords(list); + return Result.OK(pageList); + } + + /** + * 批量查询子节点 + * + * @param parentIds 父ID(多个采用半角逗号分割) + * @param parentIds + * @return 返回 IPage + * @return + */ +// @AutoLog(value = "文章栏目-批量获取子数据") + @ApiOperation(value = "文章栏目-批量获取子数据", notes = "文章栏目-批量获取子数据") + @GetMapping("/getChildListBatch") + public Result getChildListBatch(@RequestParam("parentIds") String parentIds) { + try { + QueryWrapper queryWrapper = new QueryWrapper<>(); + List parentIdList = Arrays.asList(parentIds.split(",")); + queryWrapper.in("pid", parentIdList); + List list = cmsColumnService.list(queryWrapper); + IPage pageList = new Page<>(1, 10, list.size()); + pageList.setRecords(list); + return Result.OK(pageList); + } catch (Exception e) { + log.error(e.getMessage(), e); + return Result.error("批量查询子节点失败:" + e.getMessage()); + } + } + + /** + * 添加 + * + * @param cmsColumn + * @return + */ +// @AutoLog(value = "文章栏目-添加") + @ApiOperation(value = "文章栏目-添加", notes = "文章栏目-添加") + @PostMapping(value = "/add") + public Result add(@RequestBody CmsColumn cmsColumn) { + LoginUser principal = (LoginUser) SecurityUtils.getSubject().getPrincipal(); + cmsColumn.setCreateBy(principal.getUsername()); + cmsColumnService.addCmsColumn(cmsColumn); + return Result.OK("添加成功!"); + } + + /** + * 编辑 + * + * @param cmsColumn + * @return + */ +// @AutoLog(value = "文章栏目-编辑") + @ApiOperation(value = "文章栏目-编辑", notes = "文章栏目-编辑") + @PutMapping(value = "/edit") + public Result edit(@RequestBody CmsColumn cmsColumn) { + cmsColumnService.updateCmsColumn(cmsColumn); + return Result.OK("编辑成功!"); + } + + /** + * 通过id删除 + * + * @param id + * @return + */ + @ApiOperation(value = "文章栏目-通过id删除", notes = "文章栏目-通过id删除") + @DeleteMapping(value = "/delete") + public Result delete(@RequestParam(name = "id", required = true) String id) { + CmsColumn cmsColumn = cmsColumnService.getById(id); + if (StringUtils.equals("99", cmsColumn.getId())) throw new JeecgBootException("文章总栏目不可删除"); + int count = cmsColumnService.count(new LambdaQueryWrapper().eq(CmsColumn::getPid, cmsColumn.getId())); + if (count > 0) throw new JeecgBootException("存在子栏目暂不可删除"); + cmsColumnService.deleteCmsColumn(id); + return Result.OK("删除成功!"); + } + + /** + * 批量删除 + * + * @param ids + * @return + */ + @AutoLog(value = "文章栏目-批量删除") + @ApiOperation(value = "文章栏目-批量删除", notes = "文章栏目-批量删除") + @DeleteMapping(value = "/deleteBatch") + public Result deleteBatch(@RequestParam(name = "ids", required = true) String ids) { + this.cmsColumnService.removeByIds(Arrays.asList(ids.split(","))); + return Result.OK("批量删除成功!"); + } + + /** + * 通过id查询 + * + * @param id + * @return + */ + @AutoLog(value = "文章栏目-通过id查询") + @ApiOperation(value = "文章栏目-通过id查询", notes = "文章栏目-通过id查询") + @GetMapping(value = "/queryById") + public Result queryById(@RequestParam(name = "id", required = true) String id) { + CmsColumn cmsColumn = cmsColumnService.getById(id); + if (cmsColumn == null) { + return Result.error("未找到对应数据"); + } + return Result.OK(cmsColumn); + } + + /** + * 导出excel + * + * @param request + * @param cmsColumn + */ + @RequestMapping(value = "/exportXls") + public ModelAndView exportXls(HttpServletRequest request, CmsColumn cmsColumn) { + return super.exportXls(request, cmsColumn, CmsColumn.class, "文章栏目"); + } + + /** + * 通过excel导入数据 + * + * @param request + * @param response + * @return + */ + @RequestMapping(value = "/importExcel", method = RequestMethod.POST) + public Result importExcel(HttpServletRequest request, HttpServletResponse response) { + return super.importExcel(request, response, CmsColumn.class); + } + +} diff --git a/jeecg-boot/jeecg-boot-module-cms/src/main/java/org/jeecg/modules/cms/admin/entity/CmsArticle.java b/jeecg-boot/jeecg-boot-module-cms/src/main/java/org/jeecg/modules/cms/admin/entity/CmsArticle.java new file mode 100644 index 0000000..a044bdb --- /dev/null +++ b/jeecg-boot/jeecg-boot-module-cms/src/main/java/org/jeecg/modules/cms/admin/entity/CmsArticle.java @@ -0,0 +1,111 @@ +package org.jeecg.modules.cms.admin.entity; + + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; +import org.jeecg.common.aspect.annotation.Dict; +import org.jeecgframework.poi.excel.annotation.Excel; +import org.springframework.format.annotation.DateTimeFormat; + +import java.io.Serializable; +import java.util.Date; + +/** + * @Description: 文章管理 + * @Author: jeecg-boot + * @Date: 2023-03-27 + * @Version: V1.0 + */ +@Data +@TableName("cms_article") +@Accessors(chain = true) +@EqualsAndHashCode(callSuper = false) +@ApiModel(value = "cms_article对象", description = "文章管理") +public class CmsArticle implements Serializable { + private static final long serialVersionUID = 1L; + + /** + * 主键 + */ + @TableId(type = IdType.ASSIGN_ID) + @ApiModelProperty(value = "主键") + private String id; + /** + * 创建人 + */ + @ApiModelProperty(value = "创建人") + @Dict(dictTable = "sys_user", dicCode = "username", dicText = "realname") + private String createBy; + /** + * 创建日期 + */ + @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @ApiModelProperty(value = "创建日期") + private Date createTime; + /** + * 更新人 + */ + @ApiModelProperty(value = "更新人") + private String updateBy; + /** + * 更新日期 + */ + @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @ApiModelProperty(value = "更新日期") + private Date updateTime; + + + @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @ApiModelProperty(value = "发布时间") + private Date publishTime; + /** + * 文章标题 + */ + @Excel(name = "文章标题", width = 15) + @ApiModelProperty(value = "文章标题") + private String title; + /** + * 内容 + */ + @Excel(name = "内容", width = 15) + @ApiModelProperty(value = "内容") + private String content; + /** + * 状态 + */ + @Excel(name = "状态", width = 15) + @ApiModelProperty(value = "状态 0:未发布,1:已发布") + @Dict(dicCode = "isShow") + private String status; + /** + * 所属栏目 + */ + @Excel(name = "所属栏目", width = 15) + @ApiModelProperty(value = "所属栏目") + private String columnId; + /** + * 栏目 + */ + @Excel(name = "栏目", width = 15) + @ApiModelProperty(value = "栏目") + private String columnName; + /** + * 来源 + */ + @Excel(name = "来源", width = 15) + @ApiModelProperty(value = "来源") + private String source; + + @ApiModelProperty(value = "源url") + private String originUrl; +} diff --git a/jeecg-boot/jeecg-boot-module-cms/src/main/java/org/jeecg/modules/cms/admin/entity/CmsColumn.java b/jeecg-boot/jeecg-boot-module-cms/src/main/java/org/jeecg/modules/cms/admin/entity/CmsColumn.java new file mode 100644 index 0000000..0ead20d --- /dev/null +++ b/jeecg-boot/jeecg-boot-module-cms/src/main/java/org/jeecg/modules/cms/admin/entity/CmsColumn.java @@ -0,0 +1,96 @@ +package org.jeecg.modules.cms.admin.entity; + + +import java.io.Serializable; +import java.util.Date; +import java.math.BigDecimal; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import com.fasterxml.jackson.annotation.JsonFormat; +import org.springframework.format.annotation.DateTimeFormat; +import org.jeecgframework.poi.excel.annotation.Excel; +import org.jeecg.common.aspect.annotation.Dict; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +import java.io.UnsupportedEncodingException; + +/** + * @Description: 文章栏目 + * @Author: jeecg-boot + * @Date: 2023-03-27 + * @Version: V1.0 + */ +@Data +@TableName("cms_column") +@ApiModel(value = "cms_column对象", description = "文章栏目") +public class CmsColumn implements Serializable { + private static final long serialVersionUID = 1L; + + /** + * 主键 + */ + @TableId(type = IdType.ASSIGN_ID) + @ApiModelProperty(value = "主键") + private String id; + /** + * 创建人 + */ + @ApiModelProperty(value = "创建人") + @Dict(dictTable = "sys_user",dicCode = "username",dicText = "realname") + private String createBy; + /** + * 创建日期 + */ + @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @ApiModelProperty(value = "创建日期") + private Date createTime; + /** + * 更新人 + */ + @ApiModelProperty(value = "更新人") + private String updateBy; + /** + * 更新日期 + */ + @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @ApiModelProperty(value = "更新日期") + private Date updateTime; + /** + * 显示 + */ + @Excel(name = "显示", width = 15) + @ApiModelProperty(value = "显示") + @Dict(dicCode = "isShow") + private String isShow; + /** + * 排序 + */ + @Excel(name = "排序", width = 15) + @ApiModelProperty(value = "排序") + private Integer sort; + /** + * 名称 + */ + @Excel(name = "名称", width = 15) + @ApiModelProperty(value = "名称") + private String name; + /** + * 父级节点 + */ + @Excel(name = "父级节点", width = 15) + @ApiModelProperty(value = "父级节点") + private String pid; + /** + * 是否有子节点 + */ + @Excel(name = "是否有子节点", width = 15, dicCode = "yn") + @Dict(dicCode = "yn") + @ApiModelProperty(value = "是否有子节点") + private String hasChild; +} diff --git a/jeecg-boot/jeecg-boot-module-cms/src/main/java/org/jeecg/modules/cms/admin/mapper/CmsArticleMapper.java b/jeecg-boot/jeecg-boot-module-cms/src/main/java/org/jeecg/modules/cms/admin/mapper/CmsArticleMapper.java new file mode 100644 index 0000000..f32e0a0 --- /dev/null +++ b/jeecg-boot/jeecg-boot-module-cms/src/main/java/org/jeecg/modules/cms/admin/mapper/CmsArticleMapper.java @@ -0,0 +1,15 @@ +package org.jeecg.modules.cms.admin.mapper; + + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.jeecg.modules.cms.admin.entity.CmsArticle; + +/** + * @Description: 文章管理 + * @Author: jeecg-boot + * @Date: 2023-03-27 + * @Version: V1.0 + */ +public interface CmsArticleMapper extends BaseMapper { + +} diff --git a/jeecg-boot/jeecg-boot-module-cms/src/main/java/org/jeecg/modules/cms/admin/mapper/CmsColumnMapper.java b/jeecg-boot/jeecg-boot-module-cms/src/main/java/org/jeecg/modules/cms/admin/mapper/CmsColumnMapper.java new file mode 100644 index 0000000..1c93eca --- /dev/null +++ b/jeecg-boot/jeecg-boot-module-cms/src/main/java/org/jeecg/modules/cms/admin/mapper/CmsColumnMapper.java @@ -0,0 +1,23 @@ +package org.jeecg.modules.cms.admin.mapper; + + +import org.apache.ibatis.annotations.Param; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.jeecg.modules.cms.admin.entity.CmsColumn; + +/** + * @Description: 文章栏目 + * @Author: jeecg-boot + * @Date: 2023-03-27 + * @Version: V1.0 + */ +public interface CmsColumnMapper extends BaseMapper { + + /** + * 编辑节点状态 + * @param id + * @param status + */ + void updateTreeNodeStatus(@Param("id") String id,@Param("status") String status); + +} diff --git a/jeecg-boot/jeecg-boot-module-cms/src/main/java/org/jeecg/modules/cms/admin/service/ICmsArticleService.java b/jeecg-boot/jeecg-boot-module-cms/src/main/java/org/jeecg/modules/cms/admin/service/ICmsArticleService.java new file mode 100644 index 0000000..5820e85 --- /dev/null +++ b/jeecg-boot/jeecg-boot-module-cms/src/main/java/org/jeecg/modules/cms/admin/service/ICmsArticleService.java @@ -0,0 +1,15 @@ +package org.jeecg.modules.cms.admin.service; + + +import com.baomidou.mybatisplus.extension.service.IService; +import org.jeecg.modules.cms.admin.entity.CmsArticle; + +/** + * @Description: 文章管理 + * @Author: jeecg-boot + * @Date: 2023-03-27 + * @Version: V1.0 + */ +public interface ICmsArticleService extends IService { + +} diff --git a/jeecg-boot/jeecg-boot-module-cms/src/main/java/org/jeecg/modules/cms/admin/service/ICmsColumnService.java b/jeecg-boot/jeecg-boot-module-cms/src/main/java/org/jeecg/modules/cms/admin/service/ICmsColumnService.java new file mode 100644 index 0000000..fe93800 --- /dev/null +++ b/jeecg-boot/jeecg-boot-module-cms/src/main/java/org/jeecg/modules/cms/admin/service/ICmsColumnService.java @@ -0,0 +1,54 @@ +package org.jeecg.modules.cms.admin.service; + + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.service.IService; +import org.jeecg.common.exception.JeecgBootException; +import org.jeecg.modules.cms.admin.entity.CmsColumn; + +import java.util.List; + +/** + * @Description: 文章栏目 + * @Author: jeecg-boot + * @Date: 2023-03-27 + * @Version: V1.0 + */ +public interface ICmsColumnService extends IService { + + /** + * 根节点父ID的值 + */ + public static final String ROOT_PID_VALUE = "0"; + + /** + * 树节点有子节点状态值 + */ + public static final String HASCHILD = "1"; + + /** + * 树节点无子节点状态值 + */ + public static final String NOCHILD = "0"; + + /** + * 新增节点 + */ + void addCmsColumn(CmsColumn cmsColumn); + + /** + * 修改节点 + */ + void updateCmsColumn(CmsColumn cmsColumn) throws JeecgBootException; + + /** + * 删除节点 + */ + void deleteCmsColumn(String id) throws JeecgBootException; + + /** + * 查询所有数据,无分页 + */ + List queryTreeListNoPage(QueryWrapper queryWrapper); + +} diff --git a/jeecg-boot/jeecg-boot-module-cms/src/main/java/org/jeecg/modules/cms/admin/service/impl/CmsArticleServiceImpl.java b/jeecg-boot/jeecg-boot-module-cms/src/main/java/org/jeecg/modules/cms/admin/service/impl/CmsArticleServiceImpl.java new file mode 100644 index 0000000..09c5f69 --- /dev/null +++ b/jeecg-boot/jeecg-boot-module-cms/src/main/java/org/jeecg/modules/cms/admin/service/impl/CmsArticleServiceImpl.java @@ -0,0 +1,20 @@ +package org.jeecg.modules.cms.admin.service.impl; + + +import org.jeecg.modules.cms.admin.entity.CmsArticle; +import org.jeecg.modules.cms.admin.mapper.CmsArticleMapper; +import org.jeecg.modules.cms.admin.service.ICmsArticleService; +import org.springframework.stereotype.Service; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; + +/** + * @Description: 文章管理 + * @Author: jeecg-boot + * @Date: 2023-03-27 + * @Version: V1.0 + */ +@Service +public class CmsArticleServiceImpl extends ServiceImpl implements ICmsArticleService { + +} diff --git a/jeecg-boot/jeecg-boot-module-cms/src/main/java/org/jeecg/modules/cms/admin/service/impl/CmsColumnServiceImpl.java b/jeecg-boot/jeecg-boot-module-cms/src/main/java/org/jeecg/modules/cms/admin/service/impl/CmsColumnServiceImpl.java new file mode 100644 index 0000000..eb286fb --- /dev/null +++ b/jeecg-boot/jeecg-boot-module-cms/src/main/java/org/jeecg/modules/cms/admin/service/impl/CmsColumnServiceImpl.java @@ -0,0 +1,192 @@ +package org.jeecg.modules.cms.admin.service.impl; + + +import org.jeecg.common.exception.JeecgBootException; +import org.jeecg.common.util.oConvertUtils; +import org.jeecg.modules.cms.admin.entity.CmsColumn; +import org.jeecg.modules.cms.admin.mapper.CmsColumnMapper; +import org.jeecg.modules.cms.admin.service.ICmsColumnService; +import org.springframework.stereotype.Service; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import org.springframework.transaction.annotation.Transactional; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; + +/** + * @Description: 文章栏目 + * @Author: jeecg-boot + * @Date: 2023-03-27 + * @Version: V1.0 + */ +@Service +public class CmsColumnServiceImpl extends ServiceImpl implements ICmsColumnService { + + @Override + public void addCmsColumn(CmsColumn cmsColumn) { + //新增时设置hasChild为0 + cmsColumn.setHasChild(ICmsColumnService.NOCHILD); + if(oConvertUtils.isEmpty(cmsColumn.getPid())){ + cmsColumn.setPid(ICmsColumnService.ROOT_PID_VALUE); + }else{ + //如果当前节点父ID不为空 则设置父节点的hasChildren 为1 + CmsColumn parent = baseMapper.selectById(cmsColumn.getPid()); + if(parent!=null && !"1".equals(parent.getHasChild())){ + parent.setHasChild("1"); + baseMapper.updateById(parent); + } + } + baseMapper.insert(cmsColumn); + } + + @Override + public void updateCmsColumn(CmsColumn cmsColumn) { + CmsColumn entity = this.getById(cmsColumn.getId()); + if(entity==null) { + throw new JeecgBootException("未找到对应实体"); + } + String old_pid = entity.getPid(); + String new_pid = cmsColumn.getPid(); + if(!old_pid.equals(new_pid)) { + updateOldParentNode(old_pid); + if(oConvertUtils.isEmpty(new_pid)){ + cmsColumn.setPid(ICmsColumnService.ROOT_PID_VALUE); + } + if(!ICmsColumnService.ROOT_PID_VALUE.equals(cmsColumn.getPid())) { + baseMapper.updateTreeNodeStatus(cmsColumn.getPid(), ICmsColumnService.HASCHILD); + } + } + baseMapper.updateById(cmsColumn); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteCmsColumn(String id) throws JeecgBootException { + //查询选中节点下所有子节点一并删除 + id = this.queryTreeChildIds(id); + if(id.indexOf(",")>0) { + StringBuffer sb = new StringBuffer(); + String[] idArr = id.split(","); + for (String idVal : idArr) { + if(idVal != null){ + CmsColumn cmsColumn = this.getById(idVal); + String pidVal = cmsColumn.getPid(); + //查询此节点上一级是否还有其他子节点 + List dataList = baseMapper.selectList(new QueryWrapper().eq("pid", pidVal).notIn("id",Arrays.asList(idArr))); + if((dataList == null || dataList.size()==0) && !Arrays.asList(idArr).contains(pidVal) + && !sb.toString().contains(pidVal)){ + //如果当前节点原本有子节点 现在木有了,更新状态 + sb.append(pidVal).append(","); + } + } + } + //批量删除节点 + baseMapper.deleteBatchIds(Arrays.asList(idArr)); + //修改已无子节点的标识 + String[] pidArr = sb.toString().split(","); + for(String pid : pidArr){ + this.updateOldParentNode(pid); + } + }else{ + CmsColumn cmsColumn = this.getById(id); + if(cmsColumn==null) { + throw new JeecgBootException("未找到对应实体"); + } + updateOldParentNode(cmsColumn.getPid()); + baseMapper.deleteById(id); + } + } + + @Override + public List queryTreeListNoPage(QueryWrapper queryWrapper) { + List dataList = baseMapper.selectList(queryWrapper); + List mapList = new ArrayList<>(); + for(CmsColumn data : dataList){ + String pidVal = data.getPid(); + //递归查询子节点的根节点 + if(pidVal != null && !"0".equals(pidVal)){ + CmsColumn rootVal = this.getTreeRoot(pidVal); + if(rootVal != null && !mapList.contains(rootVal)){ + mapList.add(rootVal); + } + }else{ + if(!mapList.contains(data)){ + mapList.add(data); + } + } + } + return mapList; + } + + /** + * 根据所传pid查询旧的父级节点的子节点并修改相应状态值 + * @param pid + */ + private void updateOldParentNode(String pid) { + if(!ICmsColumnService.ROOT_PID_VALUE.equals(pid)) { + Integer count = baseMapper.selectCount(new QueryWrapper().eq("pid", pid)); + if(count==null || count<=1) { + baseMapper.updateTreeNodeStatus(pid, ICmsColumnService.NOCHILD); + } + } + } + + /** + * 递归查询节点的根节点 + * @param pidVal + * @return + */ + private CmsColumn getTreeRoot(String pidVal){ + CmsColumn data = baseMapper.selectById(pidVal); + if(data != null && !"0".equals(data.getPid())){ + return this.getTreeRoot(data.getPid()); + }else{ + return data; + } + } + + /** + * 根据id查询所有子节点id + * @param ids + * @return + */ + private String queryTreeChildIds(String ids) { + //获取id数组 + String[] idArr = ids.split(","); + StringBuffer sb = new StringBuffer(); + for (String pidVal : idArr) { + if(pidVal != null){ + if(!sb.toString().contains(pidVal)){ + if(sb.toString().length() > 0){ + sb.append(","); + } + sb.append(pidVal); + this.getTreeChildIds(pidVal,sb); + } + } + } + return sb.toString(); + } + + /** + * 递归查询所有子节点 + * @param pidVal + * @param sb + * @return + */ + private StringBuffer getTreeChildIds(String pidVal,StringBuffer sb){ + List dataList = baseMapper.selectList(new QueryWrapper().eq("pid", pidVal)); + if(dataList != null && dataList.size()>0){ + for(CmsColumn tree : dataList) { + if(!sb.toString().contains(tree.getId())){ + sb.append(",").append(tree.getId()); + } + this.getTreeChildIds(tree.getId(),sb); + } + } + return sb; + } + +} diff --git a/jeecg-boot/jeecg-boot-module-cms/src/main/java/org/jeecg/modules/cms/front/CmsHomePageController.java b/jeecg-boot/jeecg-boot-module-cms/src/main/java/org/jeecg/modules/cms/front/CmsHomePageController.java new file mode 100644 index 0000000..fdfdde1 --- /dev/null +++ b/jeecg-boot/jeecg-boot-module-cms/src/main/java/org/jeecg/modules/cms/front/CmsHomePageController.java @@ -0,0 +1,70 @@ +package org.jeecg.modules.cms.front; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.jeecg.common.api.vo.Result; +import org.jeecg.common.system.query.QueryGenerator; +import org.jeecg.modules.cms.admin.entity.CmsArticle; +import org.jeecg.modules.cms.admin.entity.CmsColumn; +import org.jeecg.modules.cms.admin.service.ICmsArticleService; +import org.jeecg.modules.cms.admin.service.ICmsColumnService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import javax.servlet.http.HttpServletRequest; +import java.util.List; + +@Api(tags = "cms首页") +@RestController +@RequestMapping("/cms/front") +@Slf4j +public class CmsHomePageController /*extends JeecgController*/ { + + @Autowired + private ICmsColumnService cmsColumnService; + + @Autowired + private ICmsArticleService cmsArticleService; + + @ApiOperation(value = "文章栏目-列表", notes = "文章栏目-列表") + @GetMapping(value = "/getColumnList") + public Result getColumnList(HttpServletRequest req) { + List list = cmsColumnService.list(new LambdaQueryWrapper() + .eq(CmsColumn::getIsShow, "1") + .orderByAsc(CmsColumn::getSort)); + return Result.OK(list); + } + + @ApiOperation(value = "通过栏目类型获取文章列表", notes = "通过栏目类型获取文章列表") + @GetMapping(value = "/getArticleListByColumn") + public Result getArticleListByColumn(CmsArticle cmsArticle, + @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, + @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, + HttpServletRequest req) { + QueryWrapper queryWrapper = QueryGenerator.initQueryWrapper(cmsArticle, req.getParameterMap()); + queryWrapper.eq("status", "1"); + queryWrapper.eq("column_id", cmsArticle.getColumnId()); + queryWrapper.last("order by publish_time desc"); + Page page = new Page(pageNo, pageSize); + IPage pageList = cmsArticleService.page(page, queryWrapper); + return Result.OK(pageList); + } + + @ApiOperation(value = "通过文单标题查询", notes = "通过文单标题查询") + @GetMapping(value = "/getByArticleTitle") + public Result getByArticleTitle(CmsArticle cmsArticle, HttpServletRequest req) { + List list = cmsArticleService.list(new LambdaQueryWrapper() + .eq(CmsArticle::getStatus, "1") + .eq(CmsArticle::getTitle, cmsArticle.getTitle()) + .orderByDesc(CmsArticle::getPublishTime)); + return Result.OK(list); + } +} diff --git a/jeecg-boot/jeecg-boot-module-cms/src/main/java/org/jeecg/modules/cms/webmagic/controller/NewsWebMagicController.java b/jeecg-boot/jeecg-boot-module-cms/src/main/java/org/jeecg/modules/cms/webmagic/controller/NewsWebMagicController.java new file mode 100644 index 0000000..565a87b --- /dev/null +++ b/jeecg-boot/jeecg-boot-module-cms/src/main/java/org/jeecg/modules/cms/webmagic/controller/NewsWebMagicController.java @@ -0,0 +1,67 @@ +package org.jeecg.modules.cms.webmagic.controller; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.jeecg.modules.cms.webmagic.service.NewsPageProcessor; +import org.jeecg.modules.cms.webmagic.service.NewsPipeline; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import us.codecraft.webmagic.Spider; + +@Api(tags = "国际学院-新闻联动态爬虫") +@RestController +@RequestMapping("/cms/newWebMagic") +@Slf4j +public class NewsWebMagicController { + + @Autowired + private NewsPipeline pipeline; + + @Autowired + private NewsPageProcessor pageProcessor; + + @ApiOperation(value = "国际学院-新联动态爬虫", notes = "国际学院-新联动态爬虫") + @GetMapping(value = "/crawl") + public void crawl() { + String page1 = "http://sie.huanghuai.edu.cn/index.php/item-list-category-13151.shtml"; + String pageOther = "http://sie.huanghuai.edu.cn/index.php/item-list-category-13151-page-"; + String url = ""; + try { + Spider.create(pageProcessor) + .addUrl(page1) + // 抓取到的数据存数据库 + .addPipeline(pipeline) + // 开启2个线程抓取 + .thread(1) + // 异步启动爬虫 + .start(); + } catch (Exception ex) { + log.error("数据抓取异常:", ex.getMessage()); + log.error("定时抓取数据线程执行异常", ex); + } +// for (int i = 60; i <= 65; i++) { +// if (i == 1) { +// url = page1; +// } else { +// url = pageOther + (i + 1) + ".html"; +// } +// log.info("the page {} url:{}", i, url); +// try { +// Spider.create(pageProcessor) +// .addUrl(url) +// // 抓取到的数据存数据库 +// .addPipeline(pipeline) +// // 开启2个线程抓取 +// .thread(3) +// // 异步启动爬虫 +// .start(); +// } catch (Exception ex) { +// log.error("第[{}]页数据抓取异常:", i, ex.getMessage()); +// log.error("定时抓取数据线程执行异常", ex); +// } +// } + } +} diff --git a/jeecg-boot/jeecg-boot-module-cms/src/main/java/org/jeecg/modules/cms/webmagic/service/NewsPageProcessor.java b/jeecg-boot/jeecg-boot-module-cms/src/main/java/org/jeecg/modules/cms/webmagic/service/NewsPageProcessor.java new file mode 100644 index 0000000..c5b3af7 --- /dev/null +++ b/jeecg-boot/jeecg-boot-module-cms/src/main/java/org/jeecg/modules/cms/webmagic/service/NewsPageProcessor.java @@ -0,0 +1,93 @@ +package org.jeecg.modules.cms.webmagic.service; + +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.jeecg.common.util.DateUtils; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Element; +import org.jsoup.select.Elements; +import org.springframework.stereotype.Component; +import us.codecraft.webmagic.Page; +import us.codecraft.webmagic.Site; +import us.codecraft.webmagic.processor.PageProcessor; + +import java.text.SimpleDateFormat; +import java.util.LinkedList; +import java.util.List; +import java.util.Optional; + +@Component +@Slf4j +public class NewsPageProcessor implements PageProcessor { + + private Site site = Site.me().setRetryTimes(3).setSleepTime(1000); + + @Override + public void process(Page page) { + log.info("the page.url ****** = " + page.getUrl()); +// log.info("page= " + page.getHtml().toString()); + + /** + *
+ * 首页 >> + * 走进学院 >> + * 学院新闻 >> + * 详细内容 + * + * 该div包含详细内容 说明是文章详情页面,需求处理,其它页面不处理 + */ + page.putField("flag", page.getHtml().xpath("//div[@class='position']/a[4]/html()").toString()); + if (StringUtils.isBlank(page.getResultItems().get("flag"))) { + //文章日期 +// List dateList = page.getHtml().xpath("//ul[@class='label_ul_b']/li/span[@class='label_datatime']/html()").all(); +// List urlList = page.getHtml().xpath("//ul[@class='label_ul_b']/li/a/html()").all(); + List liNodes = page.getHtml().xpath("//ul[@class='label_ul_b']/li/html()").all(); + String currentDate = DateUtils.date2Str(new SimpleDateFormat("yyyy-MM-dd")); + Optional.ofNullable(liNodes).orElse(new LinkedList<>()).forEach(li -> { + if (StringUtils.isNotEmpty(li)) { + Element body = Jsoup.parse(li).body(); + Elements allElements = body.getAllElements(); + String date = allElements.get(1).text(); + String dateStr = date.substring(1, date.length() - 1); +// log.info("dateStr = " + dateStr); + String href = allElements.get(2).attr("href"); +// log.info("url = " + href); + //只抓取当前日期发布的文章 + if (StringUtils.equals(currentDate, dateStr)) { + page.addTargetRequest(href); + } + } + }); + + //要抓取的文章url +// List requestList = page.getTargetRequests(); +// requestList.forEach(e -> { +// log.info("当前页,文章列表:{}", e.getUrl()); +// }); + + + // 如果是列表页,跳过此页,pipeline不进行后续处理 + //不处理列表的页面,只处理详情页数据 + page.setSkip(true); + } else { //文章信息 + + //文章标题 + page.putField("title", page.getHtml().xpath("//div[@class='layout_txtcontent_title']/html()").toString()); + //文章内容 + page.putField("content", page.getHtml().xpath("//div[@class='layout_txtcontent_content']/html()").toString()); + +// 日期:2023-04-03 00:00:00 + String publishTimeHtml = page.getHtml().xpath("//div[@class='layout_txtcontent_info']/text()").toString(); + String publishTime = publishTimeHtml.substring(4, 23); + //发布时间 + page.putField("publishTime", publishTime); +// log.info("publishTime2-------------:{}", publishTime); + } + + } + + @Override + public Site getSite() { + return site; + } +} diff --git a/jeecg-boot/jeecg-boot-module-cms/src/main/java/org/jeecg/modules/cms/webmagic/service/NewsPipeline.java b/jeecg-boot/jeecg-boot-module-cms/src/main/java/org/jeecg/modules/cms/webmagic/service/NewsPipeline.java new file mode 100644 index 0000000..bebd41d --- /dev/null +++ b/jeecg-boot/jeecg-boot-module-cms/src/main/java/org/jeecg/modules/cms/webmagic/service/NewsPipeline.java @@ -0,0 +1,59 @@ +package org.jeecg.modules.cms.webmagic.service; + +import cn.hutool.core.date.DateTime; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import lombok.extern.slf4j.Slf4j; +import org.jeecg.common.util.DateUtils; +import org.jeecg.modules.cms.admin.entity.CmsArticle; +import org.jeecg.modules.cms.admin.entity.CmsColumn; +import org.jeecg.modules.cms.admin.service.ICmsArticleService; +import org.jeecg.modules.cms.admin.service.ICmsColumnService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.util.ObjectUtils; +import us.codecraft.webmagic.ResultItems; +import us.codecraft.webmagic.Task; +import us.codecraft.webmagic.pipeline.Pipeline; + +import java.text.SimpleDateFormat; +import java.util.Date; + +@Component +@Slf4j +public class NewsPipeline implements Pipeline { + + @Autowired + private ICmsArticleService iCmsArticleService; + + @Autowired + private ICmsColumnService iCmsColumnService; + + public void process(ResultItems resultItems, Task task) { +// log.info("the url:{}", resultItems.getRequest().getUrl()); +// log.info("the title:{}", resultItems.get("title").toString()); +// log.info("the content:{}", resultItems.get("content").toString()); + String publishTime = resultItems.get("publishTime").toString(); + CmsArticle cmsArticle = new CmsArticle(); + cmsArticle.setSource("国际学院"); + cmsArticle.setStatus("1"); + Date date = DateUtils.str2Date(publishTime, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")); + cmsArticle.setPublishTime(date); + cmsArticle.setCreateTime(date); + cmsArticle.setTitle(resultItems.get("title").toString()); + cmsArticle.setContent(resultItems.get("content").toString()); + cmsArticle.setCreateBy("admin"); + cmsArticle.setOriginUrl(resultItems.getRequest().getUrl()); + CmsColumn cmsColumn = iCmsColumnService.getOne(new LambdaQueryWrapper() + .eq(CmsColumn::getName, "专业动态")); + if (!ObjectUtils.isEmpty(cmsColumn)) { + cmsArticle.setColumnId(cmsColumn.getId()); + cmsArticle.setColumnName(cmsColumn.getName()); + } + try { + iCmsArticleService.save(cmsArticle); + log.info("保存文章成功:{}", resultItems.get("title").toString()); + } catch (Exception e) { + log.error("保存文章失败", e.getMessage()); + } + } +} diff --git a/jeecg-boot/jeecg-boot-module-cms/src/main/java/org/jeecg/modules/cms/webmagic/task/NewsAsyncJob.java b/jeecg-boot/jeecg-boot-module-cms/src/main/java/org/jeecg/modules/cms/webmagic/task/NewsAsyncJob.java new file mode 100644 index 0000000..d977409 --- /dev/null +++ b/jeecg-boot/jeecg-boot-module-cms/src/main/java/org/jeecg/modules/cms/webmagic/task/NewsAsyncJob.java @@ -0,0 +1,53 @@ +package org.jeecg.modules.cms.webmagic.task; + +import lombok.extern.slf4j.Slf4j; +import org.jeecg.common.util.DateUtils; +import org.jeecg.modules.cms.webmagic.service.NewsPageProcessor; +import org.jeecg.modules.cms.webmagic.service.NewsPipeline; +import org.quartz.*; +import org.springframework.beans.factory.annotation.Autowired; +import us.codecraft.webmagic.Spider; + +/** + * @Description: 同步定时任务 + *

+ * 此处的同步是指 当定时任务的执行时间大于任务的时间间隔时 + * 会等待第一个任务执行完成才会走第二个任务 + * @author: taoyan + * @date: 2020年06月19日 + */ +@PersistJobDataAfterExecution +@DisallowConcurrentExecution +@Slf4j +public class NewsAsyncJob implements Job { + + @Autowired + private NewsPipeline pipeline; + + @Autowired + private NewsPageProcessor pageProcessor; + + @Override + public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException { + log.info(" NewsAsyncJob Execution key:" + jobExecutionContext.getJobDetail().getKey()); + log.info(String.format("NewsAsyncJob-开始时间:" + DateUtils.getTimestamp())); + + String urlPage1 = "http://sie.huanghuai.edu.cn/index.php/item-list-category-13151.shtml"; +// String urlPageOther = "http://sie.huanghuai.edu.cn/index.php/item-list-category-13151-page-"; +// String url = ""; + try { + Spider.create(pageProcessor) + .addUrl(urlPage1) + // 抓取到的数据存数据库 + .addPipeline(pipeline) + // 开启2个线程抓取 + .thread(1) + // 异步启动爬虫 + .start(); + } catch (Exception ex) { + log.error("数据抓取异常:", ex.getMessage()); + log.error("定时抓取数据线程执行异常", ex); + } + } + +} diff --git a/jeecg-boot/jeecg-boot-module-cms/src/main/java/org/jeecg/modules/cms/webmagic/task/NewsWebMagicTask.java b/jeecg-boot/jeecg-boot-module-cms/src/main/java/org/jeecg/modules/cms/webmagic/task/NewsWebMagicTask.java new file mode 100644 index 0000000..95a236a --- /dev/null +++ b/jeecg-boot/jeecg-boot-module-cms/src/main/java/org/jeecg/modules/cms/webmagic/task/NewsWebMagicTask.java @@ -0,0 +1,71 @@ +//package org.jeecg.modules.cms.webmagic.task; +// +//import lombok.extern.slf4j.Slf4j; +//import org.jeecg.modules.cms.webmagic.service.NewsPageProcessor; +//import org.jeecg.modules.cms.webmagic.service.NewsPipeline; +//import org.springframework.beans.factory.annotation.Autowired; +//import org.springframework.scheduling.annotation.Scheduled; +//import org.springframework.stereotype.Component; +//import us.codecraft.webmagic.Spider; +// +//@Slf4j +//@Component +//public class NewsWebMagicTask { +// +// @Autowired +// private NewsPipeline pipeline; +// +// @Autowired +// private NewsPageProcessor pageProcessor; +// +// // 每天23点执行一次 +//// @Scheduled(cron = "0 0 23 * * ?") +// //@Scheduled(cron = "0 40 15 * * ?") +// // 每隔1分钟执行一次 +//// @Scheduled(cron = "0 */3 * * * ?") +// public void crawl() { +// //第1页 http://sie.huanghuai.edu.cn/index.php/item-list-category-13151.shtml +// //第2页 http://sie.huanghuai.edu.cn/index.php/item-list-category-13151-page-2.html +// //第3页 http://sie.huanghuai.edu.cn/index.php/item-list-category-13151-page-3.html +// // ...... +// //第65页 http://sie.huanghuai.edu.cn/index.php/item-list-category-13151-page-65.html +// +// String urlPage1 = "http://sie.huanghuai.edu.cn/index.php/item-list-category-13151.shtml"; +// String urlPageOther = "http://sie.huanghuai.edu.cn/index.php/item-list-category-13151-page-"; +// String url = ""; +// try { +// Spider.create(pageProcessor) +// .addUrl(urlPage1) +// // 抓取到的数据存数据库 +// .addPipeline(pipeline) +// // 开启2个线程抓取 +// .thread(1) +// // 异步启动爬虫 +// .start(); +// } catch (Exception ex) { +// log.error("数据抓取异常:", ex.getMessage()); +// log.error("定时抓取数据线程执行异常", ex); +// } +//// for (int i = 1; i <= 9; i++) { +//// if (i == 1) { +//// url = urlPage1; +//// } else { +//// url = urlPageOther + (i + 1) + ".html"; +//// } +//// log.info("the page {} url:{}", i, url); +//// try { +//// Spider.create(pageProcessor) +//// .addUrl(url) +//// // 抓取到的数据存数据库 +//// .addPipeline(pipeline) +//// // 开启2个线程抓取 +//// .thread(3) +//// // 异步启动爬虫 +//// .start(); +//// } catch (Exception ex) { +//// log.error("第[{}]页数据抓取异常:", i, ex.getMessage()); +//// log.error("定时抓取数据线程执行异常", ex); +//// } +//// } +// } +//} diff --git a/jeecg-boot/jeecg-boot-module-cms/src/main/java/org/jeecg/modules/cms/webmagic/task/SampleJobTest.java b/jeecg-boot/jeecg-boot-module-cms/src/main/java/org/jeecg/modules/cms/webmagic/task/SampleJobTest.java new file mode 100644 index 0000000..0dad758 --- /dev/null +++ b/jeecg-boot/jeecg-boot-module-cms/src/main/java/org/jeecg/modules/cms/webmagic/task/SampleJobTest.java @@ -0,0 +1,22 @@ +package org.jeecg.modules.cms.webmagic.task; + +import lombok.extern.slf4j.Slf4j; +import org.jeecg.common.util.DateUtils; +import org.quartz.Job; +import org.quartz.JobExecutionContext; +import org.quartz.JobExecutionException; + +/** + * 示例不带参定时任务 + * + * @Author Scott + */ +@Slf4j +public class SampleJobTest implements Job { + + @Override + public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException { + log.info(" >>>>>>>>SampleJobTest Execution key:"+jobExecutionContext.getJobDetail().getKey()); + log.info(String.format(" 普通定时任务 SampleJobTest,时间:" + DateUtils.getTimestamp())); + } +} diff --git a/jeecg-boot/jeecg-boot-module-system/pom.xml b/jeecg-boot/jeecg-boot-module-system/pom.xml index 3e29d9a..15b797d 100644 --- a/jeecg-boot/jeecg-boot-module-system/pom.xml +++ b/jeecg-boot/jeecg-boot-module-system/pom.xml @@ -110,6 +110,18 @@ 3.17 + + org.jeecgframework.boot + jeecg-boot-module-cms + ${jeecgboot.version} + + + org.slf4j + slf4j-log4j12 + + + + diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/logback-spring.xml b/jeecg-boot/jeecg-boot-module-system/src/main/resources/logback-spring.xml index acad24b..dc0c4f9 100644 --- a/jeecg-boot/jeecg-boot-module-system/src/main/resources/logback-spring.xml +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/logback-spring.xml @@ -1,7 +1,7 @@ - + @@ -74,4 +74,4 @@ - \ No newline at end of file + diff --git a/jeecg-boot/pom.xml b/jeecg-boot/pom.xml index 7e14ac4..603c159 100644 --- a/jeecg-boot/pom.xml +++ b/jeecg-boot/pom.xml @@ -51,6 +51,7 @@ jeecg-boot-base jeecg-boot-module-system + jeecg-boot-module-cms @@ -169,40 +170,40 @@ ${jeecgboot.version} --> - - - org.jeecgframework.boot - jeecg-boot-starter-job - ${jeecgboot.version} - + + + + + + - - - org.jeecgframework.boot - jeecg-boot-starter-lock - ${jeecgboot.version} - + + + + + + - - - org.jeecgframework.boot - jeecg-boot-starter-rabbitmq - ${jeecgboot.version} - + + + + + + - - - com.qiniu - qiniu-java-sdk - ${qiniu-java-sdk.version} - - - okhttp - com.squareup.okhttp3 - - - + + + + + + + + + + + + @@ -212,11 +213,11 @@ ${dom4j.version} - - org.redisson - redisson - ${redisson.version} - + + + + +