Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

企业版、政务版

企业版、政务版没有store入口

在后续的企业版和政务版中我们取消了store功能,相关代码如下所示。

企业版、政务版没有store入口示例图1

企业版、政务版没有store入口示例图2

store主要面向开源版本和开发版本,企业版及政务版的数据结构和开源版有差异,会使得其数据结构被store中某些插件下载时执行的DDL语句破坏。

因此建议使用开源版本进入store下载模板然后再导入到企业版和政务版中。

模板(有演示站的)导入企业版或政务版的步骤

Tip

从开源版本升级到企业版、政务版,可以通过分享插件迁移文章、栏目、模板等相关数据

  1. 数据备份,导入会删除(当前站)所有的文章、栏目、自定义相关数据;可以手动备份数据和模板相关资源,或者通过分享插件备份
  2. 通过开源系统后台安装分享插件,在菜单管理中找到Store分享,然后复制菜单json,然后将这个菜单json在政务版导入;怎么进MStore?
  3. 开源MCMS仓库的pom找到store-client依赖并添加到企业版或政务版的pom中
  4. 没有站群忽略这步,有站群并且是站群配置是开启的,需要在mdiy_model表中添加APP_ID字段,导入完成后移除APP_ID字段即可,这里以mysql为例
ALTER TABLE `mdiy_model` ADD COLUMN `APP_ID` bigint(19) NULL AFTER `NOT_DEL`
  1. 企业版本需要增加这一步,政务版本忽略;需要执行sql,这里以mysql为例
-- 导入前执行
ALTER TABLE `cms_content` ADD COLUMN `CONTENT_STYLE` varchar(255) NULL AFTER `DEL`;

-- 导入完后 执行下面的sql移除
ALTER TABLE `cms_content` DROP COLUMN `CONTENT_STYLE`;
  1. 启动企业版或政务版,导入分享菜单,将在开源导出的zip文件导入(注意备份文章、栏目表数据),除mysql其他版本数据库导入说明
  2. 删除Store分享菜单,移除store-client依赖

Tip

导入时,默认导入模版类型字典的第一个值,要确保导入正确,可以让模版类型字典只保留一个值,这样能确保导入到对应字典的站点风格中

企业版政务版 除mysql其他版本数据库 通过分享插件导入皮肤说明

  1. 解压皮肤包后进入data/目录,确定是否包含模型数据,模型数据以model_开头

  2. 不含模型数据如图: 企业版政务版 除mysql其他版本数据库 通过分享插件导入皮肤说明示例图1 则可直接通过分享插件导入下载的皮肤压缩包。

  3. 包含模型数据如图: 企业版政务版 除mysql其他版本数据库 通过分享插件导入皮肤说明示例图2 将模板文件夹(包含.htm的文件夹)通过工具(如idea)导入,全局搜索模板文件找到modelName、tableName、modelId的相关代码,注释或删除; 企业版政务版 除mysql其他版本数据库 通过分享插件导入皮肤说明示例图3 后续如果需要使用这个模型,可使用代码生成器生成模型代码。

    将模型相关代码注释后,再删除模型数据文件(model_开头的文件),再手动压缩文件,还原压缩包,注意压缩的层级要和导出的层级一致。最后通过分享插件导入新压缩包。

代码更新

首先第一次下载源代码之后,请务必通过git仓库管理好下载的源代码,平台不定期会更新订单中的代码,如遇到技术专员提示升级代码,可以通过当初平台绑定的订单信息下载最新的源代码,直接覆盖本地的代码,再通过仓库比对的方式进行查看更新的部分。

插件依赖

平台选配的插件通过沟通群技术单独提供,包括插件的sql文件、菜单json、源代码。
组织机构为例:
插件依赖示例图1
将插件文件夹直接复制到工程目录里面
插件依赖示例图2

修改/pom.xml与/ms-mcms/pom.xml 增加插件依赖

Tip

如果还存在页面404问题,请重新编译项目重启,推荐使用默认maven配置以及mvn命令行重新编译,避免ide环境问题导致编译失败

初始化数据

  1. doc/ddl.sql 表机构
  2. doc/init.sql 初始化数据,插件依赖的初始化数据
  3. doc/data.sql 演示数据,如果不需要可以不执行
  4. doc/organization.json 菜单json,复制json直接在菜单导入

Tip

doc下面文件具体每个插件数量不一样,具体以提供的为准

版本比对

推荐用户下载代码后直接发布到自己的git仓库,后续下载代码覆盖本地与git仓库进行代码比对。数据库的更新比对方式,可以通过创建新的数据并导入最新SQL脚本,通过Navicat进行结构比对。
版本比对示例图

更新父pom.xml

更新父pom.xml示例图

  1. modules 增加 <module>ms-morganization</module>
  2. dependencies 增加依赖
<dependency>
    <groupId>net.mingsoft</groupId>
    <artifactId>ms-morganization</artifactId>
    <version>${ms.version}</version>
</dependency>

更新ms-mcms\pom.xml

dependencies 增加依赖

<dependency>
    <groupId>net.mingsoft</groupId>
    <artifactId>ms-morganization</artifactId>
    <version>${ms.version}</version>
</dependency>

后台页面404、模板管理读取不到模板文件、模板上传到错误路径等(工作区间)

排除方法:设置working directory(工作区间)
后台页面404、模板管理读取不到模板文件、模板上传到错误路径等(工作区间)示例图1

Tip

单项目多模块下启动时候必须设置 Working directory 目录(MSApplication.java所在模块的目录,这里是D:\work\gov\ms-mcms),然后重启项目。

后台页面404、模板管理读取不到模板文件、模板上传到错误路径等(工作区间)示例图2
检查ms-mcms/pom.xml配置,注释掉排除配置

屏蔽堆栈打印信息

屏蔽堆栈打印信息示例图1 屏蔽上面的堆栈信息 屏蔽堆栈打印信息示例图2 设置后 页面不再输出堆栈信息 是空白页

设置异常信息

设置异常信息示例图1 避免异常信息中暴露库表结构 设置异常信息示例图2

设置sql注入异常提示信息

设置sql注入异常提示信息示例图

required a bean of type 'org.springframework.cache.CacheManager'

required a bean of type 'org.springframework.cache.CacheManager'示例图1

required a bean of type 'org.springframework.cache.CacheManager'示例图2

ehcache.xml没有打进jar包内,导致启动失败

数据传输加密

不允许前端明文传递数据,对传递数据做加密处理

通过获取公私钥配置,对传输数据进行加密

数据传输加密示例图

  • 前端加密参考片段

// login.ftl页面
...
ms.http.post(ms.manager + "/login.do", {
    managerName:that.rsaEncrypt(that.form.managerName),
    managerPassword:that.rsaEncrypt(that.form.managerPassword),
...

// 加密方法示例
rsaEncrypt:function(pwd){
    var that = this;
    var encrypt = new JSEncrypt();
    // publicKey 从后台获取的公钥
    encrypt.setPublicKey(that.publicKey);
    var encryptPwd = encrypt.encrypt(pwd)
    return encryptPwd
},

  • 后端解密参考片段

后端接收参数解密后不符合预期时,一般都是有前置的业务对参数进行了处理,尤其是aop,可以在前置业务中(aop)中就对参数进行解密处理


LoginAction

// privateKey 查询获取私钥
//开始解密
manager.setManagerName(RSAUtils.rsaDecode(manager.getManagerName(),privateKey));
manager.setManagerPassword(RSAUtils.rsaDecode(manager.getManagerPassword(),privateKey));

修改密码、忘记密码

通过控制台打印的信息,获取当前输入密码的加密结果(验证码要正确输入) 修改密码、忘记密码示例图

获取到加密结果后,修改数据库

生成文章内容为空

生成文章内容为空示例图

一般是缓存数据被清空导致,先点击清空缓存,再点击刷新缓存

刷新缓存后,再重新静态化生成文章

Tip

系统非正常重启都会导致缓存丢失,例如:linux下通过kill 结束进程,通常推荐重启系统之后都需要重新缓存一下

缓存管理数据

清空缓存或刷新缓存时,已缓存文章总数和实际文章总数没有对应的问题 缓存管理数据示例图1

一般出现这种情况都是产生了脏数据,如 某些文章所属栏目为不存在的栏目或是父栏目下有文章

-- 查询文章中所属栏目不存在的文章数据,可使用sql排查,下面的以mysql为例
SELECT
	cms_content.* 
FROM
	cms_content
	LEFT JOIN cms_category ON cms_content.CATEGORY_ID = cms_category.id 
WHERE
	cms_category.id IS NULL;


-- 查询父栏目下的文章

SELECT
	* 
FROM
	cms_content
	LEFT JOIN cms_category ON cms_content.CATEGORY_ID = cms_category.id 
WHERE
	cms_category.LEAF = 0

缓存管理数据示例图2

清空缓存清不到0的情况,一般是在有缓存时手动操作数据库删除了文章导致的,常见于站群情况

可以删除对应的缓存文件,或者增加一个清空全部缓存的方法

contentCache.deleteAll();

快速去掉铭软相关标识与引导信息

快速去掉铭软相关标识与引导信息示例图

点击 系统设置下的 后台UI配置,可以快速设置登陆界面、后台logo、后台的信息提示

Tip

如需要隐藏表单上的引导信息,可以通过关闭 隐藏信息提示达到效果

政务版 发布到 功能

政务版 发布到 功能示例图

在多皮肤的基础上增加了发布到,可以实现例如 内网数据只在内网显示、外网只在外网显示。

需要栏目绑定好列表内容模板

新增文章必须选则发布到内网或外网。具体根据文章所属栏目绑定的模板决定,比如在某个栏目绑定了外网模板,那么栏目下的文章就需要选择发布到外网,如果不设置发布到,则文章不会生成。

如果某个栏目同时绑定了内外网模板,那么栏目下的文章内外网按需设置,如果只设置内网,那么就只有内网会生成文章。

Tip

比如幻灯栏目这种没有页面展示的栏目,可以创建一个空模板文件(如 empty.htm )并将其绑定到这些栏目上,以便正常新增删除文章。

Tip

如果修改了字典模版类型的数据,需要应用设置更新保持,栏目模版,文章的发布到进行更新同步

需要将静态文件同步到另外一台服务器使用(后台访问的地址与前台用户访问页面地址不一致)

由于{ms:global.url/}{ms:global.host/}都是会获取后台系统的实际地址,导致部署的时候页面中存在http://xxx这种绝对地址。

如果静态化后的页面需要分发到其他服务器或访问地址不一致, 处理:

  1. 统一去掉模版中的{ms:global.url/}{ms:global.host/}标签,改用html/{ms:global.template/}方式。
  2. 同时需要将模版文件夹templatestatic目录也同步到服务器

政务版 企业版 停用默认账号

先登陆后台通过默认msopen账号创建一个账号,再在安全设置->账号安全禁用默认账号角色
政务版 企业版 停用默认账号示例图

越权说明

系统很多接口功能是通用的接口,会被很多模块业务反复调用,所以通用的接口一般不给权限标识去控制权限

例如:字典读取、栏目的读取,模版接口等,都会被很多模块会调用到, 如果加上权限标识,就要为每一个业务调用权限标识,这样会接口代码的冗余。

如果需要业务接口增加权限区分,可以通过再控制层*Action对应的方法上增加权限标识 @RequiresPermissions("标识"),如下截图

越权说明示例图1

菜单管理中需要增加权限标识 越权说明示例图2

数据量大静态化慢

如果因为数据量大导致静态化慢,可以把栏目列表模版修改为异步请求大方式获取,这样就可以减少栏目列表页面的生成。

<!--列表-->
<ul>
    <li v-for="content in contents">
        {{content.title}}
        <!--格式化时间-->
        {{ms.util.date.fmt(content.date,'yyyy-MM-dd')}}

        <!-- 获取指定位置图片 -->
        <img
            :src="getLitpic(item.litpic)"
            alt=""
        />
        <!-- 获取多张图片 -->
        <!-- 如果 litpic 为空或解析后数组为空,显示默认图片 -->
        <template v-if="!item.litpic || JSON.parse(item.litpic || '[]').length === 0">
            <img
                src="/static/images/404.png"
                alt="默认图片"
            />
        </template>
        <!-- 否则正常循环图片 -->
        <template v-else>
            <img
                v-for="pic in JSON.parse(item.litpic)"
                :src="pic.url"
                :alt="pic.name"
                :key="pic.uid"
            />
        </template>

        <!-- 文本截取 -->
        {{truncateText(item.descrip,50)}}...
    </li>
</ul>
<!--分页-->
<el-pagination background @current-change="handleCurrentChange" :page-size="pageSize" :current-page.sync="pageCur" layout="prev, pager, next, jumper" :total="pageTotal"></el-pagination>

<script>
var app = new Vue({
    el: '#app',
    data: {
        //当前页数
        pageCur: 1,
        //每页文章条数
        pageSize: 20,
        //页数总数
        pageTotal: 0,
        contents: [],
    },
    methods: {

        handleCurrentChange: function(val) {
            this.list(val)
        },
        list: function(pageNo) {
            var that = this
            ms.http.post('/gov/cms/content/list.do ', {
                typeid: '${field.typeid}',
                pageSize: that.pageSize,
                pageNo: that.pageCur,
                orderby: 'date',
                order: 'desc',
                style: 'insite',
            }).then(function(data) {
                if (data.result) {
                    that.contents = data.data.rows
                    that.pageTotal = data.data.total
                }

            })
        },
        /**
         * 获取指定位置的图片url,默认获取第一个
         * @param images JSON格式图片 eg:[{"url":"1.jpg","name":"1.png","uid":1},{"url":"2.jpg","name":"2.jpg","uid":2}]
         * @param position 下标
         */
        getLitpic: function(images,position) {
            var defaultImgUrl = '/static/images/404.png';
            if (!position){
                position = 0;
            }
            if (!images){
                return defaultImgUrl;
            }
            try {
                var imageArr = JSON.parse(images);
                return imageArr[position]?.url || defaultImgUrl;
            } catch (e) {
                return defaultImgUrl;
            }
        },
        /**
         * 
         * @param text 被截取的文本
         * @param length 截取长度
         */
        truncateText: function(text, length) {
            if (!text) return '';

            if (text.length <= length) {
                return text;
            }

            return text.substring(0, length);
        },
    },
    mounted: function() {
        this.list()
    },
})
</script>

自动静态化

启用开关,在涉及到文章变动如新增修改删除分发等情况下,会自动静态化首页、相关栏目页、文章详情页。

自动静态化示例图

Tip

生产环境推荐开启此功能,可以不用手动静态化页面。自动静态化地址必须和当前浏览器地址一致,否则静态化不成功,如何更改URL地址

自动静态化配置如何设置

自动静态化配置如何设置示例图

{
  "外网": [
    {
      "file": "index.htm",
      "path": "index.html"
    }
  ]
}

如上静态化首页配置,其中外网对应是模板类型字典中的名称,file对应是静态化文件名称,path对应是静态化生成路径。如上配置就是静态化index.htm模板到index.html

Tip

谨慎修改,请务必确保配置内容符合标准 JSON 格式,否则在执行静态化过程中可能会出现错误。您可以使用 JSON格式验证工具 来检查配置是否正确。

多皮肤

不同的皮肤在html文件夹下会生成对以模版名称命名的文件夹,例如:html/a模版 、html/b模版

因防火墙、安全狗、WAF之类的过滤导致文章保存失败

如果本地开发环境保存没有问题,上线部署后产生了发布文章的数据不完整(例如大于多少文字后无法保存),建议检查环境配置,如果没有防火墙、安全狗、WAF之类的配置,再检查一下容器是否限制了传送数据的长度,下面以东方通为例截图:

因防火墙、安全狗、WAF之类的过滤导致文章保存失败示例图

从外部导入管理员数据

@Autowired
private IManagerBiz managerBiz;

@RequestMapping(value = "/init",method = {RequestMethod.GET,RequestMethod.POST})
@ResponseBody
public ResultData init(HttpServletResponse response, HttpServletRequest request) {


        // 账号
        String managerName = "msshow";
        // 密码原文
        String originPwd = "Msopen@2012";
        // 昵称
        String managerNickname = "演示导入demo";
        // 管理员角色编码
        String roleId = "69";
        // 管理员标识 super或者空字符串
        String managerAdmin = "";
        // 加密后的密码
        String password = SecureUtils.password(originPwd, managerName);
        // 身份标识 第二个参数由管理员标识(managerAdmin)+角色ids(roleIds)组成,普通管理员的标识为null,角色ids按需给
        String identifier = SecureUtils.password(managerName, managerAdmin + roleId);


        ManagerEntity manager = new ManagerEntity();
        manager.setManagerName(managerName);
        manager.setManagerPassword(password);
        manager.setManagerNickName(managerNickname);
        manager.setManagerIdentifier( identifier);
        manager.setRoleIds(roleId);
        manager.setCreateDate(new Date());
        manager.setUpdateDate(new Date());
        managerBiz.save( manager);

        return ResultData.build().success();


}

从外部导入数据到内容表时,注意需要初始化的字段,否则会导致无法静态化(旧数据迁移)

Tip

由于版本迭代会有文章表结构差异,数据的默认值、结构以系统新增的数据为准。

  1. content_type 不能为NULL ,如果为空应该为空串

  2. content_display 不能为NULL, 应设置为默认0

  3. del 默认0

  4. category_id 不能为NULL,这里记录着文章所属栏目的id

  5. content_style 不能为NULL,这里关系到静态化生成目录,如果为空不会生成静态文件;建议新增 设置"发布到"后查看值

  6. progress_status 应该默认为 终审通过

  7. has_list_html、has_detail_html 未被静态化标识;建议查看数据库该字段默认值

  8. 注意content_img字段的格式,格式不对会导致回显失败!建议新增 查看默认值格式

  9. 导入数据后需要重启服务并在静态化重新刷一下缓存或在缓存管理删除缓存并重新缓存

Tip

外来文章迁移进系统时应该同步到缓存及es中,在保存成功后回调缓存文章方法及es同步文章方法。

栏目数据导入/迁移说明

栏目数据由于包含父子关系,迁移特别注意CATEGORY_PARENT_IDS与CATEGORY_PATH数据组成。如果栏目数据不多,建议手动创建栏目。

栏目数据迁移时注意,以下列表重要字段说明

  1. CATEGORY_ID 记录当前栏目的父栏目id。如果是顶级栏目,则为NULL。

  2. LEAF 记录是否是叶子节点,1为叶子节点,0为非叶子节点。当前栏目下无子栏目即称为叶子节点。

  3. TOP_ID 记录顶级栏目的id。从当前栏目出发,如果没有父栏目称为顶级栏目;否则从父栏目继续往上找。如果当前栏目为顶级栏目,则值为0;否则值为顶级栏目的id。

  4. CATEGORY_PARENT_IDS 记录所属栏目编号集合,记录顺序从顶级栏目开始,逐级往下直至记录当前栏目的父栏目,多个ID使用逗号分隔。如:1458331339823124482,1904029579523604482

  5. CATEGORY_DISPLAY 记录栏目是否在静态化时显示,enable为显示,disable为禁用。

  6. CATEGORY_IMG 记录当前栏目banner图,注意图片保存格式为

[{"url":"/upload/1/cms/category/1646209415768.png","name":"weixin.png","uid":1646209415606}]
  1. CATEGORY_PINYIN 记录当前栏目的拼音,决定静态文件访问路径,一定要有值。如:新闻,则拼音为xinwen。栏目拼音可以自定义,但不能与其他栏目重复。

  2. CATEGORY_PATH 记录当前栏目的访问层级路径,值为各层级的栏目拼音,。如新闻为顶级栏目,则值为xinwen;如果新闻有子栏目国内,那栏目国内的路径为xinwen/guonei

  3. CATEGORY_TYPE 记录栏目的类型。1为列表栏目;2为单篇栏目;3为链接栏目。

  4. CATEGORY_URLS(企业版及以上使用) 记录内容的多模版参数,格式如

[{"name":"外网","template":"out","file":"news-detail.htm"},{"name":"内网","template":"","file":""}]

参数说明:name:内、外网值由自定义字典中的模板类型决定;template:使用的模板文件夹名称;file:具体的模板文件名称。如果不太熟悉系统,建议手动绑定模板

  1. CATEGORY_LIST_URLS(企业版及以上使用) 记录列表的多模版参数,内容多模板同理。

  2. CATEGORY_LIST_URL(开源使用) 记录栏目绑定的列表模板 格式为:news-list.htm

  3. CATEGORY_URL(开源使用) 记录栏目绑定的内容模板 格式为:news-detail.htm

静态化提示后台正在静态化问题

1.开发环境检查模板可以适当减少文章数据量,手动生成时不必多次点击,后台会一直执行程序。

2.线上环境请开启自动静态化,具体操作参考本页面 '自动静态化' 问题。

Tip

静态化是多线程操作,多次点击会消耗大量线程,点击生成一次就可以,后台会持续生成静态文件直至结束

动态访问读取模板有误

1.通过/mcms/index.do?style=模板文件夹名称(out|out1) 来指定动态访问的模板 动态访问读取模板有误示例图1

2.动态静态化作用主要是让开发者快速调整模板,不需要去手动静态化查看修改模板后的效果,在生产环境建议不要开启!

3.动态访问会默认读取自定义字典里模板类型的第一个,排序不对会导致错误选择模板类型。皮肤风格会选择第一个模板类型对应的在应用设置里绑定的皮肤风格,确认都无误后再在静态化配置里开启动态静态化解析,通过ip+/mcms/index.do的方式访问。

动态访问读取模板有误示例图2

政务版过期时间说明

gov的session过期时间以后台配置(安全设置 > 账号安全 > 会话超时)的标准,yml的配置会被后台配置覆盖

政务版重置密码错误次数

成功登录或者重启服务可以重置密码错误次数; 密码错误次数用尽导致账号被锁定,可以重启服务解锁账号,修改配置表中timeout无效; 修改密码请参考 政务版重置密码错误次数示例图1

密码错误次数过多,账号被锁定,也可登录其他管理员账号在 安全设置-> 在线管理员处解锁 政务版重置密码错误次数示例图2

静态化进度条一直100%

一般是有栏目没有绑定模板导致后台一直请求,推荐先给栏目绑定好模板或选择已绑定模板的栏目进行静态化

修改加密算法后登录失败

修改加密算法后会使管理员密码失效,更改后需第一时间按以下步骤进行操作:
1.在管理员管理界面修改一名其他超级管理员的密码,

2.重启系统,

3.用已修改的超级管理员登录,恢复其他管理员密码数据。

Tip

尽量在拿到代码时确定使用的密码加密方式,避免修改加密算法,同时修改安全设置的权限避免给到普通管理员。

如何实现免密登录

在一些二次开发的场景中,会有不需要本系统登录业务的情况,对接上其他系统的登录业务并能完整使用本系统的功能; 在其他系统登录成功之后,调用本系统的接口(自行新增):

        ManagerEntity manager = managerBiz.getByManagerName(username);
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken upt = new UsernamePasswordToken(manager.getManagerName(), manager.getManagerPassword(),rememberMe);
        subject.login(upt);

还需要将密码匹配器ManagerLoginMD5CredentialsMatcherManagerLoginSM4CredentialsMatcher两个类的doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info)方法的一段业务代码注释;

ManagerLoginSM4CredentialsMatcher

        boolean matches = false;
        //国密
        SimpleAuthenticationInfo _info = (SimpleAuthenticationInfo) info;
        UsernamePasswordToken _token = (UsernamePasswordToken) token;
        //判断用户账号和密码是否正确
        SymmetricCrypto sm4 = SmUtil.sm4(SecureUtils.getSalt(_manager.getManagerName()).getBytes());
        String tokenCredentials = sm4.encryptHex(String.valueOf(_token.getPassword()));
        Object accountCredentials = getCredentials(info);
        LOGGER.debug("国密:{}", tokenCredentials);
        // 将密码加密与系统加密后的密码校验,内容一致就返回true,不一致就返回false
        matches = equals(tokenCredentials, accountCredentials);

ManagerLoginMD5CredentialsMatcher

        boolean matches = super.doCredentialsMatch(token, info);

从截出片段开始往下所有代码都注释掉,这样就避免了在其他系统登录校验后进入本系统还校验密码失败的情况.

上述办法比较高效,但缺点是会影响本系统的账号密码登录功能,可以自定义一个密码匹配器继承HashedCredentialsMatcher,实现方法并根据不同的业务场景来区分是密码登录还是其他系统的免密登录;

这里可以自定义登录令牌继承UsernamePasswordToken,利用自定义的令牌来区分是否是免密登录;最后在ShiroConfig中换上自定义的密码匹配器即可.

如何切换缓存类型为Redis

1.在yml配置中type改成redis

2.放开redis配置注释

3.配置自己正确的redis链接配置

如何切换缓存类型为Redis示例图1
4.若需要使用redis共享session,要在ShiroConfig中将部分注释的代码放开(有多处代码需改动,需注释上一行代码启用红框代码),示例如下

ShiroConfig:securityManager,defaultWebSessionManager,singleSessionControlFilter

如何切换缓存类型为Redis示例图2

如何切换缓存类型为Redis示例图3

如何切换缓存类型为Redis示例图4

文件上传失败问题

模板上传失败或者其他文件上传失败,通常都是有文件上传配置中未声明的文件类型如js、txt等;通过提示把文件类型添加到文件上传配置的文件上传类型限制中

文件上传失败问题示例图

zip压缩时,需要选择 ‘存储‘ 方式进行压缩,否则由于压缩算法不同也可能导致上传失败。参考 上传模板

上传模板出现 invalid CEN header

上传模板时出现invalid CEN header (bad entry name)错误,请检查模板文件中是否包含中文名称的文件。如果存在此类文件,请将其删除或重命名,也可在模板上传完成后再单独上传该文件。

上传模板出现 invalid CEN header示例图

更新自定义配置模型的Json数据

需要更新自定义模型,有两种方式。可以直接在原项目的基础上进行修改。保存之后重新进行导入即可。如果没有原项目,可以拖一个和原先模型命名一致的表单。且标题和字段名和原模型一致。

更新自定义配置模型的Json数据示例图

通过绑定内外网模板,不能限制内外网访问

设置内外网模板后,并非直接绑定内外网。通过模板配置,可以生成两套不同的样式和皮肤。在不同的目录下,以内外网模板命名静态化生成两套页面。栏目绑定对应模板,通过选择文章发布到,可以区分文章生成的位置。如果需要内外网配置,需要服务器允许且配置。例如允许外网IP访问其中某一个文件夹。

Tip

内外网不能使用同一个模板,如需使用同一个模板,也需要区分模板名称。如果未使用内网模板,可以不进行设置。

静态化页面只显示当前模板绑定的风格

静态化页面只显示当前模板绑定的风格示例图

  1. 在自定义字典中,找到模板类别,将不需要展示风格的字典设置为不启用,保存并刷新缓存
  2. 应用设置进行保存并刷新缓存

附属栏目只显示于当前子栏目

发布文章可勾选附属栏目,文章会同时显示于附属栏目之中,并参与分页。但是附属栏目只支持选中的栏目,其父栏目之中不显示此文章。

文章发布、审核、生成静态页面的流程说明

文章发布

  • 新增角色

    创建一个用于发布文章的角色,如 信息录入员,配置信息录入员角色的权限;权限分配的原则是 该角色负责什么菜单下的功能,就分配对应菜单下的功能权限 文章发布示例图1

  • 分配角色栏目权限

    通过超管账号,给角色分配栏目权限,限制角色只能对某些栏目下的文章进行操作 文章发布示例图2

  • 创建管理员

    创建管理员,绑定信息录入员角色 文章发布示例图3

  • 登录账号,发布文章

    栏目权限:这里可以看到,信息录入员的栏目权限是符合预期,只能操作军事栏目下的文章数据的;

    操作权限:必须要角色权限和角色在指定栏目下的权限同时拥有才有操作按钮

    如下图的新增,角色和角色在军事栏目下都有文章的新增权限,才会显示新增按钮;像删除只有栏目管理权限中分配了,但是实际角色没有删除权限,所以删除按钮是不会显示的;后台接口也做了同时需要满足的权限校验 文章发布示例图4

  • 提交审核

    如果栏目设置了审核,需要把新增的文章提交审核,文章发布部分的任务就完成了 文章发布示例图5 文章发布示例图6

  • 撤回场景

    在提交审核后,发现有错误,需要撤回(需要有权限),文章审核状态变为草稿后,再进行文章修改;提交审核后,无法对文章进行修改撤回操作会在审批日志中留痕 文章发布示例图7

审核

需要开启审核开关,并且给具体栏目配置完整审批,在未配置审核的栏目下发布的新文章直接为终审通过状态,不会进入审批流程。可以根据栏目区分不同的审核流程,审核节点“人”只支持角色,一个节点可以有多个角色,多个角色都可以看到待办任务,只需要一个角色审核通过或拒绝

  • 审核方案节点配置

    可以按需调整节点数,但是最后一个节点必须是终审通过 审核示例图1

  • 节点审核人配置

    配置时,每个审批节点至少勾选一名角色,为确保审批流程能正常走到终审节点,漏勾选的数据会被认为是不合法的。

    一个角色有连续节点审核权限,审核时会跳级;比如 信息录入员在初审节点审核时,审核通过就直接到三审; 审核示例图2

  • 文章审核操作

    为了方便设置了信息录入员角色为审核节点角色,这边给角色补充审核权限 审核示例图3

    登录信息录入员账号,查看 内容管理 > 待审文章 审核示例图4

    点击操作列的审核,可以看到录入的表单数据 审核示例图5

    点击预览,可以根据栏目绑定的模板查看文章数据在模板的展示效果 审核示例图6

    点击审核按钮,对文章进行审核 审核示例图7

    其他节点审核按上述审核操作重复即可

门户页面展示

在开启静态化配置>自动静态化后,文章状态为终审通过后,会自动静态化,产生html文件;有审核的文章 需要通过审核后,会自动静态化;没有设置审核的文章 新增后 就会自动静态化;

门户页面展示示例图1

门户页面展示示例图2

Tip

栏目不支持自动静态化,新增或更新栏目不会自动静态化栏目

首页对应更新的html文件,具体html展示效果根据首页模板决定

门户页面展示示例图3

列表页对应更新的html文件

门户页面展示示例图4

对应生成的详情页面html文件

门户页面展示示例图5

定时发布

新增文章时设置发布时间配合定时调度能够实现文章定时发布功能

Tip

注意:发布时间按天计算,只能预发布明天及以后的文章 定时调度配置每天凌晨执行静态化首页、栏目、文章

XSS过滤配置

在稳定后上线前,建议把XSS过滤配置中的拦截路径调整好,删除有关/ms/**/**此类路径。

Tip

由于自定义会有动态修改表的操作和关键字,如果上线后仍需要使用自定义相关功能,建议加上/ms/mdiy/**的配置

文件上传路径不符合预期

多次上传同一张图片时,后续的上传将直接引用第一次上传时系统产生的路径;更换图片不会影响其他地方对该图片的引用;

eg: 栏目上传一张图片,成功后保存路径为 {"url": "/upload/1/cms/category/1686219436865.jpg"};

再在文章上传这张图片,成功保存后路径仍为{"url": "/upload/1/cms/category/1686219436865.jpg"}

图片是否相同取决于图片的内容(二进制数据)是否一致,不取决与图片名称。

进入缓存管理异常

  1. 如果缓存管理使用的是redis,检查redis连接是否正常
  2. 如果是开启集团站群的情况,首先站群配置中关闭站群,然后缓存管理清空缓存;再开启站群,缓存管理中刷新缓存;建议开发阶段确定是否要使用站群避免此情况!

数据库版本

默认按照readme配置

如 dm数据库 默认mysql database-id指定mysql

应用设置没有模板设置

应用设置没有模板设置示例图 字典管理处 编辑、保存一下模板类型字典

给角色分配权限后,仍提示没有权限

  1. 审批日志, 需要审核配置 进度日志的查看权限
  2. 统计管理 管理员工作量统计 额外需要管理员的查看权限

登录显示密码最大使用天数

  1. 更换浏览器或者使用当前浏览器无痕登录
  2. 点击右上角提示信息X,重新设置密码后,再次登录

Tip

如想延迟密码最大使用天数,请在后台安全设置设置合理时间

访问任意页面提示500错误,后端提示No TaglibFactory available

访问任意页面提示500错误,后端提示No TaglibFactory available示例图

清除IDEA缓存后重新启动即可

如何合并栏目

栏目同层级情况

  1. 点击内容管理->批量移动复制菜单
  2. 选择您要合并的栏目,将数据复制到目标栏目中,再将被合并的栏目删除。

合并到父栏目情况

  1. 创建一个新的栏目,将子栏目数据复制到新的栏目中。
  2. 删除子栏目,再次将新建的栏目数据复制到父栏目中,删除新建的栏目。

启动异常

清理插件添加依赖后启动失败,报Error creating bean with name 'cleanTableAction','cleanTableBizlmpl'

解决参考: 清理插件启动失败

启动报java.nio.charset.MalformedInputException: Input length = 2

解决参考: 字符规范

启动es依赖报找不到org.elasticsearch.xcontent.ToXcontent0bject的类文件错误

解决参考: es启动

启动报错error creating bean with name "customMultipartResolver".

解决参考: 开发启动

启动后异常org.quartz.SchedulerConfigException、org.quartz.JobPersistenceException

解决参考: 定时启动

运行时异常

es同步时出现报错 cluster_block_exception index has read-only-allow-delete block

解决参考: es同步时出现报错存储空间不足

es同步报No qualifying bean of type 'net.mingsoft.gov.service.IESContentService' avaliable

解决参考: es同步时出现报no bean

聚合搜索报错Text fields are not optimised for operations that require per-document field data like aggregations and sorting...

解决参考: es聚合搜索