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

标签问题

现有字段不满足需求,给文章表等加字段,推荐使用自定义模型

不建议直接在数据库表里面加字段,建议使用自定义模型。拖拽生成,一键绑定,即可使用。

1.在代码生成器制作模型
现有字段不满足需求,给文章表等加字段,推荐使用自定义模型示例图1
2.在自定义模型处导入模型json
现有字段不满足需求,给文章表等加字段,推荐使用自定义模型示例图2
3.在栏目管理处绑定导入的模型
现有字段不满足需求,给文章表等加字段,推荐使用自定义模型示例图3
4.在文章管理处使用导入的模型
现有字段不满足需求,给文章表等加字段,推荐使用自定义模型示例图4
5.在模板中使用带自定义模型的标签,需先了解模板基本使用
现有字段不满足需求,给文章表等加字段,推荐使用自定义模型示例图5
现有字段不满足需求,给文章表等加字段,推荐使用自定义模型示例图6
现有字段不满足需求,给文章表等加字段,推荐使用自定义模型示例图7
6.根据示例代码中 计数开关 字段控制输出内容,开、关效果分别如下
现有字段不满足需求,给文章表等加字段,推荐使用自定义模型示例图8
现有字段不满足需求,给文章表等加字段,推荐使用自定义模型示例图9

基于标签变量值的HTML属性注入处理(6.2.0 及以上版本)

  • 注入风险点:属性逃逸
    • 当变量作为属性直接放入value="..."、href="..."等属性值,传入值有"会提前闭合属性,"后面的部分可以构造产生js事件产生注入

处理方案:通过${MUtil.escape(xxx)}去对输出的值做转义,需要做空值判断 <#if xxx?has_content>${MUtil.escape(xxx)}<#else>${xxx}</#if>

扩展标签输出字段

Tip

如果单纯是增加一个显示的属性,推荐使用自定义模型,简单使用,无需后台开发

场景举例:扩展的字段有需要处理的业务逻辑,这里以ContentEntity新增一个contentExtend属性为例

  1. 新增属性产生的基本修改,实体、xml等

  2. 标签修改

如果该属性需要在列表和详情展示,那么对应需要修改arclist标签和field标签(data标签按需)

这里以arclist标签为例
...
SELECT
  cms_content.id AS "id",
  content_title AS "title",
  content_short_title AS "shorttitle",
  content_author AS "author",
  content_source AS "source",
  content_out_link AS "outlink",
  content_tags AS "tags",
  content_extend AS "extend"  # 新增扩展字段属性
...
  1. 列表模板写法
{ms:arclist}
${field.title}---${field.extend}
{/ms:arclist}
  1. 栏目CategoryEntity扩展,比文章需要多一步添加实体属性
channel标签
...
cms_category.category_img as "typelitpic" ,
cms_category.category_ico as "typeico" ,
cms_category.category_extend as "typeextend", # 新增扩展字段属性
...
// CategoryEntity
...
/**
 * 获取栏目新增扩展字段属性 (标签使用) 这里的get后的属性名是上方扩展字段属性as的别名
 */
public String getTypeextend() {
    return this.categoryExtend;
}

Tip

对于二次开发的业务数据展示,不推荐新增标签获取,开发成本较高,推荐走接口获取

自定义全局标签初始配置(开源5.4.3及以上支持)

在菜单管理导入自定义全局参数菜单json

自定义全局标签初始配置(开源5.4.3及以上支持)示例图

菜单示例json数据

[{"createBy":"","id":"1821","updateBy":"57","updateDate":"2024-11-26 09:25:22","modelTitle":"自定义全局参数","modelDatetime":"2024-11-26 09:24:30","modelId":84,"modelUrl":"mdiy/tag/globalTag/config.do?modelId=1860892324126367745&isEditor=true","modelCode":"","isChild":"","modelIcon":"","modelSort":0,"modelIsMenu":1,"chick":0,"depth":1,"modelParentIds":"84","modelChildList":[{"id":"1822","modelTitle":"新增","modelDatetime":"2024-11-26 09:24:30","modelId":1821,"modelUrl":"mdiy:tag:save","modelSort":0,"modelIsMenu":0,"chick":0,"depth":2,"modelParentIds":"84,1821"},{"id":"1823","modelTitle":"编辑","modelDatetime":"2024-11-26 09:24:30","modelId":1821,"modelUrl":"mdiy:tag:update","modelSort":0,"modelIsMenu":0,"chick":0,"depth":2,"modelParentIds":"84,1821"},{"id":"1824","modelTitle":"查看","modelDatetime":"2024-11-26 09:24:30","modelId":1821,"modelUrl":"mdiy:tag:view","modelSort":0,"modelIsMenu":0,"chick":0,"depth":2,"modelParentIds":"84,1821"},{"id":"1825","modelTitle":"配置","modelDatetime":"2024-11-26 09:24:30","modelId":1821,"modelUrl":"mdiy:tag:config","modelSort":0,"modelIsMenu":0,"chick":0,"depth":2,"modelParentIds":"84,1821"}]}]

导入配套示例sql

自定义模型示例数据

INSERT INTO `mdiy_model` (`ID`, `model_json`, `model_table_name`, `model_name`, `model_id_type`, `model_type`, `model_field`, `model_custom_type`, `update_date`, `update_by`, `create_date`, `create_by`, `del`, `NOT_DEL`, `APP_ID`) VALUES (1860892324126367745, '{\"searchJson\":\"[\\n    \\n {},\\n]\\n\",\"isWebCode\":false,\"form\":\"[{\\\"type\\\":\\\"input\\\",\\\"name\\\":\\\"电话号码\\\",\\\"icon\\\":\\\"icon-danhangwenben\\\",\\\"pmofAllowUpdate\\\":1,\\\"pmofAllowGenerater\\\":1,\\\"pmofAllowRepet\\\":1,\\\"pmofAllowValidator\\\":1,\\\"pmofAllowEmpty\\\":0,\\\"pmofLength\\\":255,\\\"pmofType\\\":\\\"VARCHAR\\\",\\\"pmofJavaType\\\":\\\"String\\\",\\\"pmofSort\\\":0,\\\"likeSearch\\\":true,\\\"help\\\":\\\"标签:{ms:global.foot.tel/}\\\",\\\"options\\\":{\\\"isShow\\\":true,\\\"isFk\\\":false,\\\"readonly\\\":false,\\\"width\\\":\\\"100%\\\",\\\"repeat\\\":false,\\\"defaultValue\\\":\\\"\\\",\\\"clearable\\\":true,\\\"isLength\\\":true,\\\"lengthConfig\\\":{\\\"min\\\":0,\\\"max\\\":255},\\\"required\\\":false,\\\"dataType\\\":\\\"string\\\",\\\"isPattern\\\":false,\\\"isDataType\\\":false,\\\"pattern\\\":\\\"\\\",\\\"placeholder\\\":\\\"请输入电话号码\\\",\\\"disabled\\\":false,\\\"table\\\":{\\\"search\\\":false,\\\"show\\\":true,\\\"align\\\":\\\"left\\\"}},\\\"key\\\":\\\"INPUT_OFDLN\\\",\\\"model\\\":\\\"TEL\\\",\\\"rules\\\":\\\"[{\\\\\\\"min\\\\\\\":0,\\\\\\\"max\\\\\\\":255,\\\\\\\"message\\\\\\\":\\\\\\\"电话号码长度必须为0-255\\\\\\\"}]\\\"},{\\\"type\\\":\\\"time\\\",\\\"name\\\":\\\"底部服务时间\\\",\\\"icon\\\":\\\"icon-shijian-xianxing\\\",\\\"pmofAllowUpdate\\\":1,\\\"pmofAllowGenerater\\\":1,\\\"pmofAllowRepet\\\":1,\\\"pmofAllowValidator\\\":1,\\\"pmofAllowEmpty\\\":0,\\\"pmofType\\\":\\\"TIME\\\",\\\"pmofJavaType\\\":\\\"Date\\\",\\\"pmofSort\\\":0,\\\"pmofLength\\\":0,\\\"likeSearch\\\":false,\\\"help\\\":\\\"标签:{ms:global.foot.timeBegin/} -\\\\n{ms:global.foot.timeEnd/} \\\\n \\\",\\\"options\\\":{\\\"isShow\\\":true,\\\"defaultValue\\\":null,\\\"readonly\\\":false,\\\"disabled\\\":false,\\\"editable\\\":true,\\\"clearable\\\":true,\\\"placeholder\\\":\\\"请选择底部服务时间\\\",\\\"startPlaceholder\\\":\\\"开始时间\\\",\\\"endPlaceholder\\\":\\\"结束时间\\\",\\\"isRange\\\":true,\\\"arrowControl\\\":true,\\\"format\\\":\\\"HH:mm:ss\\\",\\\"required\\\":false,\\\"width\\\":\\\"100%\\\",\\\"table\\\":{\\\"search\\\":false,\\\"show\\\":true,\\\"width\\\":120,\\\"align\\\":\\\"center\\\"},\\\"label\\\":\\\"开始时间\\\",\\\"attachField\\\":[{\\\"type\\\":\\\"time\\\",\\\"name\\\":\\\"结束时间\\\",\\\"model\\\":\\\"TIME_END\\\",\\\"key\\\":\\\"1733127110000_98951\\\",\\\"pmofAllowUpdate\\\":1,\\\"pmofAllowGenerater\\\":1,\\\"pmofAllowRepet\\\":1,\\\"pmofAllowValidator\\\":1,\\\"pmofAllowEmpty\\\":1,\\\"pmofType\\\":\\\"TIME\\\",\\\"pmofJavaType\\\":\\\"Date\\\",\\\"pmofSort\\\":0,\\\"options\\\":{\\\"isShow\\\":true,\\\"defaultValue\\\":[],\\\"readonly\\\":false,\\\"disabled\\\":false,\\\"editable\\\":true,\\\"clearable\\\":true,\\\"placeholder\\\":\\\"请选择时间选择器\\\",\\\"startPlaceholder\\\":\\\"开始时间\\\",\\\"endPlaceholder\\\":\\\"结束时间\\\",\\\"isRange\\\":true,\\\"arrowControl\\\":true,\\\"format\\\":\\\"HH:mm:ss\\\",\\\"required\\\":false,\\\"width\\\":\\\"100%\\\",\\\"table\\\":{\\\"search\\\":false,\\\"show\\\":false,\\\"width\\\":120,\\\"align\\\":\\\"center\\\"}}}]},\\\"key\\\":\\\"TIME_NYRBY\\\",\\\"model\\\":\\\"TIME_BEGIN\\\",\\\"rules\\\":\\\"[]\\\"},{\\\"type\\\":\\\"imgupload\\\",\\\"name\\\":\\\"网站ico\\\",\\\"icon\\\":\\\"icon-tupian2\\\",\\\"pmofAllowUpdate\\\":1,\\\"pmofAllowGenerater\\\":1,\\\"pmofAllowRepet\\\":1,\\\"pmofAllowValidator\\\":1,\\\"pmofAllowEmpty\\\":0,\\\"pmofLength\\\":1000,\\\"pmofType\\\":\\\"VARCHAR\\\",\\\"pmofJavaType\\\":\\\"String\\\",\\\"pmofSort\\\":0,\\\"likeSearch\\\":false,\\\"help\\\":\\\"标签:{@ms:file global.foot.ico/}\\\",\\\"options\\\":{\\\"isShow\\\":true,\\\"defaultValue\\\":[],\\\"required\\\":false,\\\"width\\\":\\\"\\\",\\\"tokenFunc\\\":\\\"funcGetToken\\\",\\\"token\\\":\\\"\\\",\\\"domain\\\":\\\"http://pfp81ptt6.bkt.clouddn.com/\\\",\\\"disabled\\\":false,\\\"limit\\\":1,\\\"multiple\\\":false,\\\"isQiniu\\\":false,\\\"action\\\":\\\"ms.manager+\'/file/upload.do\'\\\",\\\"table\\\":{\\\"show\\\":true,\\\"align\\\":\\\"left\\\"}},\\\"key\\\":\\\"IMGUPLOAD_KKLFY\\\",\\\"model\\\":\\\"ICO\\\",\\\"rules\\\":\\\"[]\\\"},{\\\"type\\\":\\\"imgupload\\\",\\\"name\\\":\\\"底部微信二维码\\\",\\\"icon\\\":\\\"icon-tupian2\\\",\\\"pmofAllowUpdate\\\":1,\\\"pmofAllowGenerater\\\":1,\\\"pmofAllowRepet\\\":1,\\\"pmofAllowValidator\\\":1,\\\"pmofAllowEmpty\\\":0,\\\"pmofLength\\\":1000,\\\"pmofType\\\":\\\"VARCHAR\\\",\\\"pmofJavaType\\\":\\\"String\\\",\\\"pmofSort\\\":0,\\\"likeSearch\\\":false,\\\"help\\\":\\\"标签:{ms:global.contextpath/}{@ms:file global.foot.qrCode/}\\\",\\\"options\\\":{\\\"isShow\\\":true,\\\"defaultValue\\\":[],\\\"required\\\":false,\\\"width\\\":\\\"\\\",\\\"tokenFunc\\\":\\\"funcGetToken\\\",\\\"token\\\":\\\"\\\",\\\"domain\\\":\\\"http://pfp81ptt6.bkt.clouddn.com/\\\",\\\"disabled\\\":false,\\\"limit\\\":1,\\\"multiple\\\":false,\\\"isQiniu\\\":false,\\\"action\\\":\\\"ms.manager+\'/file/upload.do\'\\\",\\\"table\\\":{\\\"show\\\":true,\\\"align\\\":\\\"left\\\"}},\\\"key\\\":\\\"IMGUPLOAD_MAOHJ\\\",\\\"model\\\":\\\"QR_CODE\\\",\\\"rules\\\":\\\"[]\\\"}]\",\"isWebSubmit\":false,\"html\":\"\\n<template id=\\\"custom-model\\\">\\n    <el-form ref=\\\"form\\\" :model=\\\"form\\\" :rules=\\\"rules\\\" label-width=\\\"120px\\\" label-position=\\\"right\\\" size=\\\"default\\\" :disabled=\\\"disabled\\\" v-loading=\\\"loading\\\">\\n            <!--电话号码-->\\n\\n\\t        <el-form-item  label=\\\"电话号码\\\" prop=\\\"tel\\\">\\n\\t            <el-input\\n                        v-model=\\\"form.tel\\\"\\n                         :disabled=\\\"false\\\"\\n                          :readonly=\\\"false\\\"\\n                          :style=\\\"{width:  \'100%\'}\\\"\\n                          :clearable=\\\"true\\\"\\n                        placeholder=\\\"请输入电话号码\\\">\\n                </el-input>\\n                <div class=\\\"ms-form-tip\\\">\\n标签:{ms:global.foot.tel/}                </div>\\n\\t        </el-form-item>   \\n        <!--底部服务时间-->\\n    \\n        <el-form-item  label=\\\"底部服务时间\\\" prop=\\\"timeBegin\\\">\\n             <el-time-picker\\n                  \\n                    v-model=\\\"form.timeBegin\\\"\\n                   \\n                    :is-range=\\\"true\\\"\\n               \\n                    :readonly=\\\"false\\\"\\n                    :disabled=\\\"false\\\"\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t:editable=\\\"true\\\" :clearable=\\\"true\\\"\\n                             value-format=\\\"HH:mm:ss\\\"\\n                    \\n                    :arrow-control=\\\"true\\\" :style=\\\"{width:\'100%\'}\\\">\\n            </el-time-picker>\\n                <div class=\\\"ms-form-tip\\\">\\n标签:{ms:global.foot.timeBegin/} -\\n{ms:global.foot.timeEnd/}                </div>\\n        </el-form-item>\\n   \\n        <!--网站ico-->\\n    \\n        <el-form-item  label=\\\"网站ico\\\" prop=\\\"ico\\\">\\n             <el-upload\\n                    :file-list=\\\"form.ico\\\"\\n                    :action=\\\"ms.manager+\'/file/upload.do\'\\\"\\n                    :limit=\\\"1\\\"\\n                    multiple\\n                    :disabled=\\\"false\\\"\\n                    :data=\\\"{uploadPath:\'/global/\',\'isRename\':true,\'appId\':true}\\\"\\n                    :on-remove=\\\"icoHandleRemove\\\"\\n                    :on-exceed=\\\"icoHandleExceed\\\"\\n                    :on-preview=\\\"icoHandlePreview\\\"\\n                    :on-success=\\\"icoSuccess\\\"\\n                    :on-error=\\\"icoError\\\"\\n                    accept=\\\"image/*\\\"\\n                    list-type=\\\"picture-card\\\">\\n                <i class=\\\"el-icon-plus\\\"></i>\\n                <template #tip>\\n                  <div class=\\\"el-upload__tip\\\">最多上传1张图片</div>\\n               </template>\\n            </el-upload>\\n                <div class=\\\"ms-form-tip\\\">\\n标签:{@ms:file global.foot.ico/}                </div>\\n        </el-form-item>\\n   \\n        <!--底部微信二维码-->\\n    \\n        <el-form-item  label=\\\"底部微信二维码\\\" prop=\\\"qrCode\\\">\\n             <el-upload\\n                    :file-list=\\\"form.qrCode\\\"\\n                    :action=\\\"ms.manager+\'/file/upload.do\'\\\"\\n                    :limit=\\\"1\\\"\\n                    multiple\\n                    :disabled=\\\"false\\\"\\n                    :data=\\\"{uploadPath:\'/global/\',\'isRename\':true,\'appId\':true}\\\"\\n                    :on-remove=\\\"qrCodeHandleRemove\\\"\\n                    :on-exceed=\\\"qrCodeHandleExceed\\\"\\n                    :on-preview=\\\"qrCodeHandlePreview\\\"\\n                    :on-success=\\\"qrCodeSuccess\\\"\\n                    :on-error=\\\"qrCodeError\\\"\\n                    accept=\\\"image/*\\\"\\n                    list-type=\\\"picture-card\\\">\\n                <i class=\\\"el-icon-plus\\\"></i>\\n                <template #tip>\\n                  <div class=\\\"el-upload__tip\\\">最多上传1张图片</div>\\n               </template>\\n            </el-upload>\\n                <div class=\\\"ms-form-tip\\\">\\n标签:{ms:global.contextpath/}{@ms:file global.foot.qrCode/}                </div>\\n        </el-form-item>\\n   \\n    </el-form>\\n</template>\\n\",\"id\":1,\"script\":\"var custom_model = Vue.component(\\\"custom-model\\\",{\\n    el: \'#custom-model\',\\n    data:function() {\\n        return {\\n\\t\\t\\tloading:false,\\n            disabled:false,\\n            modelId:0,\\n            modelName: \\\"foot\\\",\\n            //表单数据\\n            form: {\\n                linkId:0,\\n                    // 电话号码\\n                    tel:\'\',\\n                    //底部服务时间\\n          timeBegin:null,\\n                    // 网站ico\\n                    ico: [],\\n                    // 底部微信二维码\\n                    qrCode: [],\\n            },\\n\\n            rules:{\\n                        // 电话号码\\n                        tel: [{\\\"min\\\":0,\\\"max\\\":255,\\\"message\\\":\\\"电话号码长度必须为0-255\\\"}],\\n            },\\n        }\\n    },\\n    watch:{\\n    },\\n    components:{\\n    },\\n    computed:{\\n    },\\n    methods: {\\n      \\tlink:function(e,field,binds){\\n      \\t\\tlet that = this;\\n            binds.forEach(function(item){\\n  \\t\\t\\t\\tms.http.post(ms.manager+\'/project/form/link.do\', {id:that.modelId,field:item.field,value:e}).then(function (res) {\\n                    if(res.result && res.data) {\\n                        that.form[ms.util.camelCaseString(item.field)]=res.data[0][item.target];\\n                    }else{\\n                        that.$notify({\\n                            title: \'失败\',\\n                            message: res.msg,\\n                            type: \'warning\'\\n                        });\\n                    }\\n                })\\n\\n            });\\n      \\t},\\n           //底部服务时间时间格式化\\n           timeBeginFormat:function(row, column, cellValue, index){\\n\\n                return row.TIME_BEGIN+\\\" - \\\"+row.TIME_END;\\n            },\\n        // ico删除\\n        icoHandleRemove: function (file, files) {\\n        \\tvar index = -1;\\n        \\tindex = this.form.ico.findIndex(function (text) {\\n        \\t\\treturn text.uid == file.uid;\\n        \\t});\\n        \\tif (index != -1) {\\n        \\t\\tthis.form.ico.splice(index, 1);\\n        \\t}\\n        },\\n        //ico上传超过限制\\n        icoHandleExceed: function (files, fileList) {\\n        \\tthis.$notify({\\n        \\t\\ttitle: \'失败\',\\n        \\t\\tmessage: \'当前最多上传1个文件\',\\n        \\t\\ttype: \'warning\'\\n        \\t});\\n        },\\n        //ico预览\\n        icoHandlePreview: function (file){\\n\\t\\t\\t\\twindow.open(file.url);\\n        },\\n        //ico上传成功\\n        icoSuccess: function (response, file, fileList) {\\n        \\tif (response.result) {\\n        \\t\\tthis.form.ico.push({\\n        \\t\\t\\turl: response.data,\\n        \\t\\t\\tname: file.name,\\n        \\t\\t\\tuid: file.uid\\n        \\t\\t});\\n        \\t} else {\\n        \\t\\tthis.$notify({\\n        \\t\\t\\ttitle: \'失败\',\\n        \\t\\t\\tmessage: response.msg,\\n        \\t\\t\\ttype: \'warning\'\\n        \\t\\t});\\n        \\t}\\n        },\\n        //ico上传失败\\n        icoError: function (response, file, fileList) {\\n        \\tresponse = response.toString().replace(\\\"Error: \\\",\\\"\\\")\\n        \\tresponse = JSON.parse(response);\\n        \\tthis.$notify({\\n        \\t\\ttitle: \'失败\',\\n        \\t\\tmessage: response.msg,\\n        \\t\\ttype: \'warning\'\\n        \\t});\\n        },        // qrCode删除\\n        qrCodeHandleRemove: function (file, files) {\\n        \\tvar index = -1;\\n        \\tindex = this.form.qrCode.findIndex(function (text) {\\n        \\t\\treturn text.uid == file.uid;\\n        \\t});\\n        \\tif (index != -1) {\\n        \\t\\tthis.form.qrCode.splice(index, 1);\\n        \\t}\\n        },\\n        //qrCode上传超过限制\\n        qrCodeHandleExceed: function (files, fileList) {\\n        \\tthis.$notify({\\n        \\t\\ttitle: \'失败\',\\n        \\t\\tmessage: \'当前最多上传1个文件\',\\n        \\t\\ttype: \'warning\'\\n        \\t});\\n        },\\n        //qrCode预览\\n        qrCodeHandlePreview: function (file){\\n\\t\\t\\t\\twindow.open(file.url);\\n        },\\n        //qrCode上传成功\\n        qrCodeSuccess: function (response, file, fileList) {\\n        \\tif (response.result) {\\n        \\t\\tthis.form.qrCode.push({\\n        \\t\\t\\turl: response.data,\\n        \\t\\t\\tname: file.name,\\n        \\t\\t\\tuid: file.uid\\n        \\t\\t});\\n        \\t} else {\\n        \\t\\tthis.$notify({\\n        \\t\\t\\ttitle: \'失败\',\\n        \\t\\t\\tmessage: response.msg,\\n        \\t\\t\\ttype: \'warning\'\\n        \\t\\t});\\n        \\t}\\n        },\\n        //qrCode上传失败\\n        qrCodeError: function (response, file, fileList) {\\n        \\tresponse = response.toString().replace(\\\"Error: \\\",\\\"\\\")\\n        \\tresponse = JSON.parse(response);\\n        \\tthis.$notify({\\n        \\t\\ttitle: \'失败\',\\n        \\t\\tmessage: response.msg,\\n        \\t\\ttype: \'warning\'\\n        \\t});\\n        },        validate:function(){\\n            var b = false\\n            this.$refs.form.validate(function(valid){\\n                b = valid;\\n            });\\n            return b;\\n        },\\n        save:function(callback) {\\n            var that = this;\\n            var url = this.formURL.save.url;\\n            if (that.form.id > 0) {\\n                url = this.formURL.update.url;\\n            }\\n            this.$refs.form.validate(function(valid) {\\n                if (valid) {\\n                    var form = JSON.parse(JSON.stringify(that.form));\\n                         //底部服务时间\\n                        if(form.timeBegin){\\n                           form.timeEnd = form.timeBegin[1];\\n                           form.timeBegin = form.timeBegin[0];                            \\n                        }\\n                        form.ico = JSON.stringify(form.ico);\\n                        form.qrCode = JSON.stringify(form.qrCode);\\n                    form.modelId = that.modelId;\\n                    ms.http.post(url, form).then(function (res) {\\n                        if(callback) {\\n                            callback(res);\\n                        }\\n                    });\\n                } else{\\n                    callback({\\n                    result:false,msg:\'请检查表单输入项\'\\n                    });\\n                }\\n            })\\n        },\\n        //获取当前foot\\n        get:function(id) {\\n            var that = this;\\n            that.loading = true;\\n            ms.http.get(this.formURL.get.url, Object.assign({\\\"modelId\\\":that.modelId},this.formURL.get.params)).then(function (res) {\\n                if(res.result&&res.data){\\n                                          \\n                        //底部服务时间 \\n                     if(res.data.timeBegin && res.data.timeEnd) {\\n                        res.data.timeBegin = [ms.util.date.fmt(res.data.timeBegin,\'HH:mm:ss\'),ms.util.date.fmt(res.data.timeEnd,\'HH:mm:ss\')];\\n                       }\\n                      if (res.data.ico) {\\n                          res.data.ico = JSON.parse(res.data.ico);\\n                          res.data.ico.forEach(function (value) {\\n                             if(value.url.substr(0,7).toLowerCase() == \\\"http://\\\" || value.url.substr(0,8).toLowerCase() == \\\"https://\\\"){\\n\\t\\t\\t\\t\\t\\t\\t } else {\\n\\t\\t\\t\\t\\t\\t\\t\\tvalue.url = ms.base + value.url;\\n\\t\\t\\t\\t\\t\\t\\t }\\n                              \\n                          });\\n                      } else {\\n                          res.data.ico = [];\\n                      }\\n                      if (res.data.qrCode) {\\n                          res.data.qrCode = JSON.parse(res.data.qrCode);\\n                          res.data.qrCode.forEach(function (value) {\\n                             if(value.url.substr(0,7).toLowerCase() == \\\"http://\\\" || value.url.substr(0,8).toLowerCase() == \\\"https://\\\"){\\n\\t\\t\\t\\t\\t\\t\\t } else {\\n\\t\\t\\t\\t\\t\\t\\t\\tvalue.url = ms.base + value.url;\\n\\t\\t\\t\\t\\t\\t\\t }\\n                              \\n                          });\\n                      } else {\\n                          res.data.qrCode = [];\\n                      }\\n                    that.form = res.data;\\n                    that.loading = false;\\n                } else {\\n                    that.loading = false;\\n                }\\n            }).catch(function (err) {\\n                console.log(err);\\n                that.loading = false;\\n            });\\n        },\\n\\n    },\\n    created:function() {\\n        var that = this;\\n        //渲染create\\n        that.get(this.form.linkId);\\n    }\\n});\",\"sql\":\"\\n-- FOOT\\nCREATE TABLE  `{model}FOOT` (\\n    `id` BIGINT(19) UNSIGNED NOT NULL AUTO_INCREMENT,\\n    `TEL` VARCHAR(255) DEFAULT NULL COMMENT \'电话号码\',\\n    `TIME_BEGIN` TIME DEFAULT NULL COMMENT \'底部服务时间\',\\n    `TIME_END` TIME DEFAULT NULL COMMENT \'结束时间\',\\n    `ICO` VARCHAR(1000) DEFAULT NULL COMMENT \'网站ico\',\\n    `QR_CODE` VARCHAR(1000) DEFAULT NULL COMMENT \'底部微信二维码\',\\n    `LINK_ID` BIGINT(20) DEFAULT NULL,\\n    `CREATE_DATE` DATETIME DEFAULT NULL COMMENT \'创建时间\',\\n    `CREATE_BY` VARCHAR(50) DEFAULT NULL COMMENT \'创建人\',\\n    `UPDATE_DATE` DATETIME DEFAULT NULL COMMENT \'修改时间\',\\n    `UPDATE_BY` VARCHAR(50) DEFAULT NULL COMMENT \'修改人\',\\n    `DEL` INT(1) DEFAULT 0 COMMENT \'删除标记\',\\n    PRIMARY KEY (`ID`) USING BTREE\\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT=\'foot\';\\n\",\"tableName\":\"FOOT\"}', '', 'foot', 1, '', '[\n    {\n    \"model\":\"tel\",\n    \"key\":\"TEL\",\n    \"field\":\"TEL\",\n    \"javaType\":\"String\",\n    \"jdbcType\":\"VARCHAR\",\n    \"name\":\"电话号码\",\n    \"type\":\"input\",\n    \"length\":\"255\",\n    \"isShow\":true,\n     \"repeat\":false,\n     \"isSearch\":false\n    }\n    ,{\n    \"model\":\"timeBegin\",\n    \"key\":\"TIME_BEGIN\",\n    \"field\":\"TIME_BEGIN\",\n    \"javaType\":\"Date\",\n    \"jdbcType\":\"TIME\",\n    \"name\":\"底部服务时间\",\n    \"type\":\"time\",\n    \"fmt\":\"HH:mm:ss\",\n    \"endModel\":\"time_end\",\n    \"length\":\"0\",\n    \"isShow\":true,\n     \"repeat\":false,\n     \"isSearch\":false\n    }\n                ,    {\n    \"model\":\"timeEnd\",\n    \"key\":\"TIME_END\",\n    \"field\":\"TIME_END\",\n    \"javaType\":\"Date\",\n    \"jdbcType\":\"TIME\",\n    \"name\":\"结束时间\",\n    \"type\":\"time\",\n    \"fmt\":\"HH:mm:ss\",\n    \"length\":\"0\",\n    \"isShow\":false,\n     \"repeat\":false,\n     \"isSearch\":false\n    }\n\n    ,{\n    \"model\":\"ico\",\n    \"key\":\"ICO\",\n    \"field\":\"ICO\",\n    \"javaType\":\"String\",\n    \"jdbcType\":\"VARCHAR\",\n    \"name\":\"网站ico\",\n    \"type\":\"imgupload\",\n    \"length\":\"1000\",\n    \"isShow\":true,\n     \"repeat\":false,\n     \"isSearch\":false\n    }\n    ,{\n    \"model\":\"qrCode\",\n    \"key\":\"QR_CODE\",\n    \"field\":\"QR_CODE\",\n    \"javaType\":\"String\",\n    \"jdbcType\":\"VARCHAR\",\n    \"name\":\"底部微信二维码\",\n    \"type\":\"imgupload\",\n    \"length\":\"1000\",\n    \"isShow\":true,\n     \"repeat\":false,\n     \"isSearch\":false\n    }\n]\n\n', 'tag', '2024-12-27 09:39:01', NULL, '2024-11-25 11:44:38', NULL, 0, 0, 'global');

自定义配置示例数据

INSERT INTO `mdiy_config` (`id`, `MODEL_ID`, `config_name`, `config_data`, `CONFIG_TYPE`, `update_date`, `update_by`, `create_date`, `create_by`, `del`, `NOT_DEL`, `APP_ID`) VALUES (1, '1860892324126367745', 'foot', '{\"timeEnd\":\"18:00:00\",\"timeBegin\":\"09:00:00\",\"ico\":\"[{\\\"url\\\":\\\"/upload/1/global/1872457333638361088.png\\\",\\\"name\\\":\\\"1869634627528175616.png\\\",\\\"uid\\\":1735263591501,\\\"status\\\":\\\"success\\\"}]\",\"qrCode\":\"[{\\\"url\\\":\\\"/upload/1/global/1872457360049893376.jpg\\\",\\\"name\\\":\\\"1869634658977067008.jpg\\\",\\\"uid\\\":1735263597758,\\\"status\\\":\\\"success\\\"}]\",\"modelId\":\"1860892324126367745\",\"tel\":\"19999999999\"}', 'tag', NULL, NULL, NULL, NULL, 0, 0, 'global');

自定义全局标签示例数据

INSERT INTO `mdiy_tag` (`id`, `tag_name`, `tag_type`, `tag_sql`, `tag_class`, `tag_description`, `MODEL_ID`, `UPDATE_BY`, `UPDATE_DATE`, `CREATE_BY`, `CREATE_DATE`, `APP_ID`, `DEL`, `NOT_DEL`) VALUES (19, 'global', 'global', 'select\n  APP_NAME as \"name\",\n  app_logo as \"logo\",\n  app_keyword as \"keyword\",\n  app_description as \"descrip\",\n  app_copyright as \"copyright\",\n  \'${contextPath}\' as \"contextpath\",\n  <#--动态解析 -->\n  <#if isDo?? && isDo>\n    \'${url}\' as \"url\",\n    \'${url}\' as \"host\",\n    \'/\' as \"html\",\n  <#--使用地址栏的域名 -->\n  <#else>\n    <#if shortSwitch?? && shortSwitch>\n      CONCAT(\'${url}\',\'${appDir}<#if appDir?has_content>/</#if>\') as \"url\",\n      \'<#if appDir?has_content>/</#if>${appDir}/\' as \"html\",\n    <#else>\n      CONCAT(CONCAT(\'${url}\',\'${html}/\'),\'<#if appDir?has_content>${appDir}/</#if>\') as \"url\",\n      CONCAT(CONCAT(\'/${html}\',\'<#if appDir?has_content>/${appDir}</#if>\'),\'/\') as \"html\",\n    </#if>\n    \'${url}\' as \"host\",\n  </#if>\n    CONCAT(CONCAT(CONCAT(CONCAT(\'template/\',id),\'/\'),app_style),\'/\') as \"style\"\nfrom app\n  <#--根据站点编号查询-->\n  <#if appId?? >\n    where id = \'${appId}\'\n  </#if>', 'globalTagService', '全局自定义标签样例', '1860892324126367745', NULL, '2024-11-25 09:36:40', '57', '2024-11-25 09:36:40', 'global', 0, 0);

自定义标签获取时间数据中时间多了个T(5.4.3及其以下版本处理)

以update_date(别名updateDate)为例,

通过string("yyyy-MM-dd HH:mm:ss") 自定义时间格式

最终格式: ${field.updateDate?replace("T"," ")?datetime?string("yyyy-MM-dd HH:mm:ss")}

设置分页文章序号

<!-- 效果  xxx(文章标题)--10、xxx--11、xxx--12...   -->

<!-- 定义计算 上一页的index值  pageSize按需填写 -->
<!-- eg:当前为第二页 , pageSize=10 则index=(2-1)*10-->
<#assign index = (page.cur?number - 1) * pageSize/>
    
{ms:arclist size=pageSize ispaging=true}
<!-- 定义计算 当前的index值 -->
<!--计算后 result = 10,11,12... -->
<#assign result = index + field.index>
${field.title}--${result}
{/ms:arclist}

标签解析报错 The following has evaluated to null or missing

提示信息一般表现为缺少了某个标签,或标签的某个属性丢失;

1、如果提示为field.date问题,优先查看 静态化报错

2、其他问题,建议先将开源中国最新的sql(mdiy_tag表)执行一遍;仍有问题,第一时间反馈,我们会立即解决

生成报错**?**

1、标签没有正确的闭合{ms:page} 最后一个/符合不能少 正确:{ms:page /}

2、字符串类型参数没有加双引号,{ms:channel type=nav } 正确:{ms:channel type="nav" },注意:数值不需要

3、include标签使用了注释 <!-- <#include "url"> --> 正确:<#-- <#include "url"> -->

报错分析参考

标签能嵌套使用吗?

目前只有部分标签支持嵌套,具体可以参考下方标签说明。

  1. 多级channel嵌套
  2. channel 与 arclist嵌套
  3. channel中使用include
  4. arclist与data嵌套

动态获取栏目或文章的typeid

当你在某个列表页时,使用ms:channel、ms:arclist两个标签时,如果不写typeid参数,会自动获取当前页面所属栏目的typeid值

文章点击量不自动增加

文章点击量是需要使用了的点击量标签${field.hit}之后数据才会增加

标签有类似if判断的功能吗?

mcms4.7.0之后的版本可以支持简单的if判断,5.1之后支持freemarker if指令

<!-- freemarker if简单使用 -->
<!-- eg: 文章如果没有上传缩略图就显示一张默认图片 -->
{ms:arclist}
<#if field.litpic>
 <img src="{@ms:file field.litpic/}"/>
<#else>
 <img src="默认图片"/>
</#if>
{/ms:arclist}

使用参考

标签属性使用无效

5.1之后属性为字符串类型的需要加引号使用例如:type="son"

页面静态化没有更新

1、按shift刷新浏览器 清除浏览器缓存
2、如果清楚缓存还不行,直接编辑一下文章,再静态化刷新页面

css文件、js文件能用标签吗?

通过link或script引入的css、js无法使用标签,通过<#include "css、js路径"/>引入的css、js可以使用标签

在模板中使用了js的模板表达式用法如${xx * xx},导致报错

在模板中使用了js的模板表达式用法如${xx * xx},导致报错示例图1 在模板中使用了js的模板表达式用法如${xx * xx},导致报错示例图2

原因:js模板表达式用法与freemarker的标签解析冲突了,导致报错。

解决方式:在模板中使用noparse标签包裹模板表达式,如 <#noparse> ${xx * xx} </#noparse> 在模板中使用了js的模板表达式用法如${xx * xx},导致报错示例图3