基于若依-内容管理动态修改,通过路由字典配置动态管理

一、Java后端

1、实体

新增了两个字段 titleImg、noticeDesc。可以动态校验(业务层)。

java 复制代码
package org.dromara.system.domain;

import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import org.dromara.common.tenant.core.TenantEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;


/**
 * 通知公告表 sys_notice
 *
 * @author Lion Li
 */
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("sys_notice")
public class SysNotice extends TenantEntity {

    /**
     * 公告ID
     */
    @TableId(value = "notice_id")
    private Long noticeId;

    /**
     * 公告标题
     */
    private String noticeTitle;

    /**
     * 公告类型(字典:sys_notice_type)
     */
    private String noticeType;

    /**
     * 标题图片
     */
    private Long titleImg;

    /**
     * 公告摘要
     */
    private String noticeDesc;

    /**
     * 公告内容
     */
    private String noticeContent;

    /**
     * 公告状态(0正常 1关闭)
     */
    private String status;

    /**
     * 备注
     */
    private String remark;

}

1、控制层

java 复制代码
package org.dromara.system.controller.system;

import cn.dev33.satoken.annotation.SaCheckPermission;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.service.DictService;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.sse.utils.SseMessageUtils;
import org.dromara.common.web.core.BaseController;
import org.dromara.system.domain.bo.SysNoticeBo;
import org.dromara.system.domain.vo.SysNoticeVo;
import org.dromara.system.service.ISysNoticeService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

/**
 * 公告 信息操作处理
 *
 * @author Lion Li
 */
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/system/notice")
public class SysNoticeController extends BaseController {

    private final ISysNoticeService noticeService;

    /**
     * 获取通知公告列表
     */
    @SaCheckPermission("system:notice:list")
    @GetMapping("/list")
    public TableDataInfo<SysNoticeVo> list(SysNoticeBo notice, PageQuery pageQuery) {
        return noticeService.selectPageNoticeList(notice, pageQuery);
    }

    /**
     * 根据通知公告编号获取详细信息
     *
     * @param noticeId 公告ID
     */
    @SaCheckPermission("system:notice:query")
    @GetMapping(value = "/{noticeId}")
    public R<SysNoticeVo> getInfo(@PathVariable Long noticeId) {
        return R.ok(noticeService.selectNoticeById(noticeId));
    }

    /**
     * 新增通知公告
     */
    @SaCheckPermission("system:notice:add")
    @Log(title = "通知公告", businessType = BusinessType.INSERT)
    @PostMapping
    public R<Void> add(@Validated @RequestBody SysNoticeBo notice) {
        int rows = noticeService.insertNotice(notice);
        if (rows <= 0) {
            return R.fail();
        }
        return R.ok();
    }

    /**
     * 修改通知公告
     */
    @SaCheckPermission("system:notice:edit")
    @Log(title = "通知公告", businessType = BusinessType.UPDATE)
    @PutMapping
    public R<Void> edit(@Validated @RequestBody SysNoticeBo notice) {
        return toAjax(noticeService.updateNotice(notice));
    }

    /**
     * 删除通知公告
     *
     * @param noticeIds 公告ID串
     */
    @SaCheckPermission("system:notice:remove")
    @Log(title = "通知公告", businessType = BusinessType.DELETE)
    @DeleteMapping("/{noticeIds}")
    public R<Void> remove(@PathVariable Long[] noticeIds) {
        return toAjax(noticeService.deleteNoticeByIds(noticeIds));
    }
}

2、小程序控制层

java 复制代码
package org.dromara.system.api.controller;

import cn.dev33.satoken.annotation.SaIgnore;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.domain.R;
import org.dromara.common.web.core.BaseController;
import org.dromara.system.domain.vo.SysNoticeVo;
import org.dromara.system.service.ISysNoticeService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * 移动端-公告|协议
 *
 * @author Lion Li
 */
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/notice/api")
public class ApiNoticeController extends BaseController {

    private final ISysNoticeService noticeService;

    /**
     * 根据公告类型获取通知公告||协议列表
     */
    @SaIgnore
    @GetMapping("/{noticeType}")
    public R<Object> userPact(@NotNull(message = "主键不能为空")
                                  @PathVariable String noticeType) {
        return R.ok(noticeService.selectNoticeByType(noticeType));
    }

    /**
     * 根据公告类型获取通知公告||协议详情
     */
    @SaIgnore
    @GetMapping("/detail/{noticeId}")
    public R<SysNoticeVo> detail(@NotNull(message = "主键不能为空")
                                @PathVariable Long noticeId) {
        return R.ok(noticeService.selectNoticeByTypeInfo(noticeId));
    }


}

3、接口

java 复制代码
package org.dromara.system.service;

import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.system.domain.bo.SysNoticeBo;
import org.dromara.system.domain.vo.SysNoticeVo;

import java.util.List;

/**
 * 公告 服务层
 *
 * @author Lion Li
 */
public interface ISysNoticeService {


    TableDataInfo<SysNoticeVo> selectPageNoticeList(SysNoticeBo notice, PageQuery pageQuery);

    /**
     * 小程序-通过公告类型查询公告信息
     * @param noticeType
     * @return
     */
    Object selectNoticeByType(String noticeType);

    /**
     * 查询公告信息
     *
     * @param noticeId 公告ID
     * @return 公告信息
     */
    SysNoticeVo selectNoticeById(Long noticeId);

    /**
     * 查询公告列表
     *
     * @param notice 公告信息
     * @return 公告集合
     */
    List<SysNoticeVo> selectNoticeList(SysNoticeBo notice);

    /**
     * 新增公告
     *
     * @param bo 公告信息
     * @return 结果
     */
    int insertNotice(SysNoticeBo bo);

    /**
     * 修改公告
     *
     * @param bo 公告信息
     * @return 结果
     */
    int updateNotice(SysNoticeBo bo);

    /**
     * 删除公告信息
     *
     * @param noticeId 公告ID
     * @return 结果
     */
    int deleteNoticeById(Long noticeId);

    /**
     * 批量删除公告信息
     *
     * @param noticeIds 需要删除的公告ID
     * @return 结果
     */
    int deleteNoticeByIds(Long[] noticeIds);

    /**
     * 小程序-通过公告ID查询公告信息
     * @param noticeId
     * @return
     */
    SysNoticeVo selectNoticeByTypeInfo(Long noticeId);
}

4、业务层

所有的校验都通过参数判断。

titleImg、noticeDesc通过字典中某个字段的json参数去判断,这里我不想改变字典的参数,我就用了不常用的cssClass字典作为json载体。

如果你还想添加其他字段,就需要在这里添加一些判断,用于后台是否需要添加。当然前端在写的时候也要判断。

java 复制代码
package org.dromara.system.service.impl;

import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.json.utils.JsonUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.system.domain.SysNotice;
import org.dromara.system.domain.SysUser;
import org.dromara.system.domain.bo.SysNoticeBo;
import org.dromara.system.domain.vo.SysDictDataVo;
import org.dromara.system.domain.vo.SysNoticeVo;
import org.dromara.system.domain.vo.SysUserVo;
import org.dromara.system.mapper.SysNoticeMapper;
import org.dromara.system.mapper.SysUserMapper;
import org.dromara.system.service.ISysDictDataService;
import org.dromara.system.service.ISysNoticeService;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.List;

/**
 * 公告 服务层实现
 *
 * @author Lion Li
 */
@RequiredArgsConstructor
@Service
public class SysNoticeServiceImpl implements ISysNoticeService {

    private final SysNoticeMapper baseMapper;
    private final SysUserMapper userMapper;
    private final ISysDictDataService dictDataService;

    @Override
    public TableDataInfo<SysNoticeVo> selectPageNoticeList(SysNoticeBo notice, PageQuery pageQuery) {
        LambdaQueryWrapper<SysNotice> lqw = buildQueryWrapper(notice);
        Page<SysNoticeVo> page = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(page);
    }

    /**
     * 小程序-通过公告类型查询公告信息
     * @param noticeType
     * @return
     */
    @Override
    public Object selectNoticeByType(String noticeType) {
        SysDictDataVo sysNoticeType = dictDataService.selectDictLabelVo("sys_notice_type", noticeType);
        if (ObjectUtil.isNull(sysNoticeType)) throw new ServiceException("公告不存在");
        String json = sysNoticeType.getCssClass();
        Dict dict = JsonUtils.parseMap(json);
        String isWechat = (String) dict.get("isWechat");
        String isLogin = (String) dict.get("isLogin");
        if (!"T".equals(isWechat)) throw new ServiceException("非法请求!");
        if ("T".equals(isLogin) && !LoginHelper.isLogin()) throw new ServiceException("请先登录!");
        return baseMapper.selectVoList(new LambdaQueryWrapper<SysNotice>()
            .select(SysNotice::getNoticeId, SysNotice::getNoticeTitle,SysNotice::getNoticeContent,
                SysNotice::getNoticeDesc, SysNotice::getTitleImg,SysNotice::getRemark)
            .eq(SysNotice::getNoticeType,noticeType)
            .eq(SysNotice::getStatus, "1")
        );
    }


    /**
     * 小程序 通过公告ID查询公告信息
     * @param noticeId
     * @return
     */
    @Override
    public SysNoticeVo selectNoticeByTypeInfo(Long noticeId) {
        SysNoticeVo sysNotice = baseMapper.selectVoById(noticeId);
        if (ObjectUtil.isNull(sysNotice)) throw new ServiceException("该公告已下线");
        if ("0".equals(sysNotice.getStatus())) throw new ServiceException("该公告已下线");
        SysDictDataVo sysNoticeType = dictDataService.selectDictLabelVo("sys_notice_type", sysNotice.getNoticeType());
        if (ObjectUtil.isNull(sysNoticeType)) throw new ServiceException("公告类型不存在");
        String json = sysNoticeType.getCssClass();
        Dict dict = JsonUtils.parseMap(json);
        String isWechat = (String) dict.get("isWechat");
        String isLogin = (String) dict.get("isLogin");
        if (!"T".equals(isWechat)) throw new ServiceException("非法请求!");
        if ("T".equals(isLogin) && !LoginHelper.isLogin()) throw new ServiceException("请先登录!");
        return sysNotice;
    }



    /**
     * 查询公告信息
     *
     * @param noticeId 公告ID
     * @return 公告信息
     */
    @Override
    public SysNoticeVo selectNoticeById(Long noticeId) {
        return baseMapper.selectVoById(noticeId);
    }

    /**
     * 查询公告列表
     *
     * @param notice 公告信息
     * @return 公告集合
     */
    @Override
    public List<SysNoticeVo> selectNoticeList(SysNoticeBo notice) {
        LambdaQueryWrapper<SysNotice> lqw = buildQueryWrapper(notice);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<SysNotice> buildQueryWrapper(SysNoticeBo bo) {
        if (StringUtils.isBlank(bo.getNoticeType())) throw new ServiceException("公告类型不能为空");
        LambdaQueryWrapper<SysNotice> lqw = Wrappers.lambdaQuery();
        lqw.like(StringUtils.isNotBlank(bo.getNoticeTitle()), SysNotice::getNoticeTitle, bo.getNoticeTitle());
        lqw.eq(SysNotice::getNoticeType, bo.getNoticeType());
        if (StringUtils.isNotBlank(bo.getCreateByName())) {
            SysUserVo sysUser = userMapper.selectVoOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getUserName, bo.getCreateByName()));
            lqw.eq(SysNotice::getCreateBy, ObjectUtil.isNotNull(sysUser) ? sysUser.getUserId() : null);
        }
        lqw.orderByAsc(SysNotice::getNoticeId);
        return lqw;
    }

    /**
     * 新增公告
     *
     * @param bo 公告信息
     * @return 结果
     */
    @Override
    public int insertNotice(SysNoticeBo bo) {
        validateNotice(bo);
        SysNotice notice = MapstructUtils.convert(bo, SysNotice.class);
        return baseMapper.insert(notice);
    }

    /**
     * 修改公告
     *
     * @param bo 公告信息
     * @return 结果
     */
    @Override
    public int updateNotice(SysNoticeBo bo) {
        validateNotice(bo);
        SysNotice notice = MapstructUtils.convert(bo, SysNotice.class);
        return baseMapper.updateById(notice);
    }

    /**
     * 新增修改前的校验
     */
    private void validateNotice(SysNoticeBo bo) {
        if (StringUtils.isBlank(bo.getNoticeType())) throw new ServiceException("公告类型不能为空");
        SysDictDataVo sysNoticeType = dictDataService.selectDictLabelVo("sys_notice_type", bo.getNoticeType());
        if (ObjectUtil.isNull(sysNoticeType)) throw new ServiceException("公告类型不存在");
        String json = sysNoticeType.getCssClass();
        Dict dict = JsonUtils.parseMap(json);
        String isOne = (String) dict.get("isOne");
        String titleImg = (String) dict.get("titleImg");
        String noticeDesc = (String) dict.get("noticeDesc");

        if (StringUtils.isBlank(titleImg)) bo.setTitleImg(null);
        if (StringUtils.isBlank(noticeDesc)) bo.setNoticeDesc(null);

        if (StringUtils.isNotBlank(bo.getStatus()) && "1".equals(bo.getStatus())
            && "T".equals(isOne)) {
            baseMapper.update(new LambdaUpdateWrapper<SysNotice>()
                .eq(SysNotice::getNoticeType, bo.getNoticeType())
                .set(SysNotice::getStatus, "0")
            );
        }
    }


    /**
     * 删除公告对象
     *
     * @param noticeId 公告ID
     * @return 结果
     */
    @Override
    public int deleteNoticeById(Long noticeId) {
        return baseMapper.deleteById(noticeId);
    }

    /**
     * 批量删除公告信息
     *
     * @param noticeIds 需要删除的公告ID
     * @return 结果
     */
    @Override
    public int deleteNoticeByIds(Long[] noticeIds) {
        return baseMapper.deleteByIds(Arrays.asList(noticeIds));
    }


}

注:这里用到 dictDataService.selectDictLabelVo()实现就是返回一个字典实体。可以自己去定义接口。参考如下:

java 复制代码
    /**
     * 查询字典数据
     *
     * @param dictType  字典类型
     * @param dictValue 字典键值
     * @return 字典标签
     */
    @Override
    public SysDictDataVo selectDictLabelVo(String dictType, String dictValue) {
        return baseMapper.selectVoOne(new LambdaQueryWrapper<SysDictData>()
            .select(SysDictData::getDictLabel,SysDictData::getCssClass,SysDictData::getRemark)
            .eq(SysDictData::getDictType, dictType)
            .eq(SysDictData::getDictValue, dictValue));
    }

二、前端

前端我就不详细描述,给出主要的几个方法,具体配置根据你的表单来弄。

1、通过路由获取内容管理的类型

javascript 复制代码
const router = useRouter()
queryParams.value.noticeType = router.currentRoute.value.name

规定:

配置路由时,路由名称和字典名称要一致,但是路由配置首字母小写,字典首字母大写。

路由组件路径统一通一个index.vue这里时:system/notice/index.vue

2、通过字典获取配置参数

javascript 复制代码
const noticeConfig = ref({
  isLogin: 'F', // 是否需要校验登录 F否T是
  isOne: 'F', // 发布项目是否唯一
  isWechat: 'F', // 是否是微信接口
  label: '公告', // 标题
  noticeDesc: 'F', // 摘要
  titleImg: 'F' // 封面图
});
const {  sys_notice_type } = toRefs<any>(useDict( 'sys_notice_type'));

function handleDictChange(newDict) {
  if (newDict && newDict.length > 0) {
    newDict.forEach(item => {
      if (item.value == router.currentRoute.value.name) {
        noticeConfig.value = JSON.parse(item.elTagClass)
        noticeConfig.value.label = item.label
      }
    })
  }
}

// 监听字典值变化
watch(sys_notice_type, (newValue, oldValue) => {
  handleDictChange(newValue)
}, {
  deep: true, // 深度监听,确保对象内部变化也能触发
  immediate: true // 立即执行一次,获取初始值
})

表单可以通过判断来实现是否显示:

html 复制代码
<ElTableColumn label="摘要" prop="noticeDesc" :show-overflow-tooltip="true" v-if="noticeConfig.noticeDesc && 'T' == noticeConfig.noticeDesc" />

这里字典配置参数如下:

java 复制代码
{"isOne":"T","titleImg":"F","noticeDesc":"F","isLogin":"T","isWechat":"T"}

三、总结

通过字典和路由的配置,灵活的配置内容管理。再做客户开发中,我们经常会遇到一堆内容管理:通知、公告、关于我们、隐私协议、用户协议、看板等等。这些其实都是一个富文本输入为主。或多或少一个字段。为此我们单独去给他弄一个代码,实属复杂。

这篇很大程度同化不必要的内容管理,可以灵活的实现不改代码就能添加一个目录。

如果这个小技巧对你有所帮助,请不要吝啬你的点赞和收藏。

相关推荐
Rysxt_2 小时前
Vuex 教程 从入门到实践
前端·javascript·vue.js
青云交2 小时前
Java 大视界 -- 基于 Java 的大数据可视化在城市空气质量监测与污染溯源中的应用
java·spark·lstm·可视化·java 大数据·空气质量监测·污染溯源
森语林溪2 小时前
大数据环境搭建从零开始(十七):JDK 17 安装与配置完整指南
java·大数据·开发语言·centos·vmware·软件需求·虚拟机
郝开3 小时前
Spring Boot 2.7.18(最终 2.x 系列版本)1 - 技术选型:连接池技术选型对比;接口文档技术选型对比
java·spring boot·spring
小猪咪piggy3 小时前
【项目】小型支付商城 MVC/DDD
java·jvm·数据库
知兀4 小时前
【Spring/SpringBoot】SSM(Spring+Spring MVC+Mybatis)方案、各部分职责、与Springboot关系
java·spring boot·spring
向葭奔赴♡4 小时前
Spring IOC/DI 与 MVC 从入门到实战
java·开发语言
早退的程序员4 小时前
记一次 Maven 3.8.3 无法下载 HTTP 仓库依赖的排查历程
java·http·maven
向阳而生,一路生花4 小时前
redis离线安装
java·数据库·redis