# 自定义js

需求说明

模型在框架中有自己的默认逻辑方案,支持通过引入动态js变更相关属性进行自定义逻辑变更,接下来将展示进行进行自定义操作

  1. 动态js目录情况
.
└─ async-module -------------------------- 模型分包
    └─ plugin  --------------------------- 模型自定义js文件夹
        ├─ business  ----------------------- 【业务】模块js
        │  ├─ text ------------------------- 模块名称
        │  │   ├─ wjx_goods_edit.js
        │  │   ├─ wjx_goods_list.js
        │  │   ├─ wjx_test3_edit.js
        │  │   └─ wjx_test3_list.js
        │  └─ others  ---------------------- 其他【业务】模块
        │
        └─ frame  -------------------------- 框架级别js
           ├─ modelDesign ------------------ 模块名称
           │   ├─ sys_md_module_edit.js
           │   ├─ sys_md_module_list.js
           │   ├─ sys_module_field_list.js
           │   └─ sys_module_link_edit.js
           └─ others  ---------------------- 其他框架模块
  1. 新增js文件
    找到以上目录,项目中添加js一般操作business业务文件夹即可
  • 在business下新建模块文件夹,以业务模块含义 + 驼峰命名【一个模块可以存放多个模型编码下的动态js,模块的命名可以不用局限当前模型编码】,例如textDemo
  • 以模型编码textAge作为关键词,下划线 + 全小写 相连命名自定义js【模型编码有明确短词连接的,例如 TextAge , textAge , text-age , text_Age , Text_age 等,都需要转化成 text_age_
  • js只有两种,编辑与查看共用_edit.js, 列表使用_list.js,使用两者作为js名称的末尾标识
.
└─ business
    └─ textDemo 
        ├─ text_age_list.js     --- textAge为模型编码mdCode
        └─ text_age_edit.js  

文件创建成功,进入下一步

  1. 模型设计器中配置js路径
    框架会默认设置src/async-module/plugin作为根路径,模型设计器中的配置需要补充后面路径.
    例如js所在路径是src/async-module/plugin/frame/modelDesign/sys_md_module_edit.js,则模型设计器中配置只需要填入/frame/modelDesign/sys_md_module_edit.js注意路径最前面不要漏写/

# 列表js配置

# 列表数据url

export default {
    dataUrl () {
        return '/aaa'
    },
}

# 按钮

模型说明

模型列表默认含有以下按钮

[
    { id: 'add', name: '新增', icon: 'bd-add', poritity: 5, type: 'primary' },
    { id: 'edit', name: '修改', icon: 'bd-edit', poritity: 10, type: 'primary', position: 'bottom' },
    { id: 'view', name: '查看', icon: 'bd-view', poritity: 15, type: 'primary', position: 'row' },
    { id: 'delete', name: '删除', icon: 'bd-delete', poritity: 40, type: 'secondary', position: 'page,bottom', isMultiple: true },
]

:::

    1. 清空所有按钮
export default {
    buttons: [],
}
    1. 隐藏部分默认按钮
export default {
    buttons: [
        {
            id: 'view',
            /* 
                1. 直接赋值
                2. 支持函数
             */
            isHide: true,
            // isHide: () => true,
        }
    ]
}
    1. 更改默认按钮事件
export default {
    buttons: [
        {
            /** 按钮属性
             * 1. id: 必须、唯一
             * 2. name:按钮显示名称
             * 3. icon:按钮图标
             * 4. poritity:按钮排序号
             * 5. type: 按钮样式,可选值【primary、warning、danger、success、operate】
             * 6. position:按钮位置,可选值【right、row、page、pageBottom】;Array/String,可多选;默认值:['page']
             *      page:收缩在页面上
             *      row:点击行数据时会执行该按钮的事件;buttons中只能存在一个row;当itemClick存在时,会执行itemClick的内容,此参数无效
             *      right:单个行数据拥有按钮
             *      pageBottom:页面底部
             * 7. isMultiple:如果按钮可以多选,使用此方法,会先弹出行checkbox
             * 8. click:按钮点击事件
             * 备注:当id为【add、edit、view、delete】当中的某一个时,除id、click 外的其余属性非必填
             *      已有默认值(src/setting/frame-const.js文件中的listAttrs中有定义)
             */
            id: 'delete',
            // name: '删除',
            // icon: 'bd-delete',
            // poritity: 40,
            // type: 'danger',
            // position: 'right, page', // 按钮位置(每行数据右侧滑动、页面)
            // isMultiple: true, // 多选
            click () {
                this.$message('我是自定义删除事件!')
                let config = {
                    type: 'moduleEdit',
                    mdCode: 'goods_copy',
                    customSetting: {},
                    btnList: [{
                        id: 'save',
                        name: '确定',
                        click () {
                            this.validate().then(res => {
                                console.log(res)
                            })
                        }
                    }],
                }
                this.$showDialog(config)
            }
        }
    ],
}
    1. 添加默认按钮事件
export default {
    buttons: [
        /** 按钮属性
         * 1. id: 必须、唯一
         * 2. name:按钮显示名称
         * 3. icon:按钮图标
         * 4. poritity:按钮排序号
         * 5. type: 按钮样式,可选值【primary、warning、danger、success、operate】
         * 6. position:按钮位置,可选值【right、row、page、pageBottom】;Array/String,可多选;默认值:['page']
         *      page:收缩在页面上
         *      row:点击行数据时会执行该按钮的事件;buttons中只能存在一个row;当itemClick存在时,会执行itemClick的内容,此参数无效
         *      right:单个行数据拥有按钮
         *      pageBottom:页面底部
         * 7. isMultiple:如果按钮可以多选,使用此方法,会先弹出行checkbox
         * 8. click:按钮点击事件
         * 备注:当id为【add、edit、view、delete】当中的某一个时,除id、click 外的其余属性非必填
         *      已有默认值(src/setting/frame-const.js文件中的listAttrs中有定义)
         */
        {
            id: 'customBtn',
            name: '自定义',
            icon: 'bd-jsonFormat',
            type: 'success',
            position: 'right, page', // 按钮位置(每行数据右侧滑动、页面)
            isMultiple: true, // 多选
            click () {
                this.$message('我是自定义新增的按钮!')
            }
        }, {
            id: 'getListData',
            name: '获取当前列表数据',
            icon: 'bd-jsonFormat',
            type: 'success',
            position: 'pageBottom', // 按钮位置(页面底部)
            click() {
                console.log('getShowData', this.getShowData())
            }
        }
    ],
}
    1. 支持使用priority进行按钮排序

说明

不使用priority字段将默认为999999,会排在通用按钮后面

框架默认按钮priority为以下:
    新增【add】:5
    修改【edit】:10
    查看【view】:15
    删除【delete】:40
ps:自定义修改按钮:
	1. 如果按钮id一致,没有定义priority属性,那么按照默认排序
    2. 如果按钮id一致,有定义priority属性,那么按照重新定义的priority的值进行排序
export default {
    buttons: [
        { 
            id: 'operateEvt',
            name: '操作',
            icon: 'bd-reset',
            type: 'primary',
            position: 'bottom',
            priority: 35, // 渲染时将会渲染在【导出按钮】与【删除按钮】中间
            click: function (btnObj) {
                // do something
            }
        }, { 
            id: 'add', // 没有定义priority属性,priority 为默认值 5,
            name: '重写的新增按钮',
            icon: 'bd-add',
            type: 'primary',
            click: function (btnObj) {
                // do something
            }
        }, { 
            id: 'edit',
            name: '重写的修改按钮',
            icon: 'bd-edit',
            type: 'primary',
            position: 'row',
            priority: 1, // 重新定义了priority属性,渲染时将会渲染在【新增按钮】按钮的前面
            click: function (btnObj) {
                // do something
            }
        },
    ],
}
    1. 使用函数,动态返回按钮数据(更加灵活)

注意

使用函数时,与直接传数组是存在差别的

  1. 直接传数组是相当于添加按钮,页面上会将原有按钮与这部分添加按钮进行合并
  2. 使用函数时,返回的按钮数据,页面上将直接使用此展示
export default {
    /**
     * @param {Array} defaultBtnList 默认的按钮列表数据
     */
    buttons: function (defaultBtnList) {
        // this:这里this指向为moduleList/index.vue页面所在作用域
        // 定义一条按钮数据
        let resetBtn = { 
            id: 'reset',
            name: '重置',
            icon: 'reset',
            type: 'warning',  // primary/warning/danger/success
            position: 'right, page',    // right/row/page/pageBottom
            click: function (btnObj) {
                // btnObj: 当前按钮对象数据 {id:'reset', name...}
                // 定义获取列表选中数据
                let selection = this.getSelection()
                // 获取核心列表所在组件作用域,若列表需要刷新时调用
                let listPageRef = this.listPageRef()
                // 列表刷新
                listPageRef.init()
            }
        }
        // 在原有按钮组最前面添加一条按钮数据
        defaultBtnList.unshift(resetBtn)
        // 注意:必须return回去最终的按钮数组
        return defaultBtnList
    }
}

注意

函数最终必须将按钮结果数组return回去

    1. 按钮位置
属性 可选值 描述
position 'row' 点击行(页面不显示)
'right' 行数据右侧(左滑)
'bottom' 行数据底部
'page' 页面
export default {
    buttons: [
        {
            id: 'row',
            name: '点击行触发',
            position: 'row'
        },
        {
            id: 'right',
            name: '行数据右侧(左滑)',
            position: 'right'
        },
        {
            id: 'bottom',
            name: '行数据底部',
            position: 'bottom'
        },
        {
            id: 'page',
            name: '页面下方加号内',
            position: 'page'
        },
        {
            id: 'meantime',
            name: '可同时多个位置',
            position: 'right page'
        }
    ]
}
    1. 按钮主题

主题说明

按钮主题可选值取决于按钮位置值

export default {
    buttons: [
        {
            id: 'cus1',
            position: 'bottom',
            type: 'primary', // 可选值:primary secondary
        },
        {
            id: 'cus2',
            position: 'right',
            type: 'primary', // 可选值:primary warning success danger secondary
        }
    ]
}

# 列表展现形式

属性 可选值 描述
styleList '0' 独占一行布局
'1' 两栏卡片布局
export default {
    styleList: '1'
}

# 列表数据接口

export default {
    dataUrl: function () {
        // 返回自定义接口地址
        return `/xxx/xxxxxx/xxxxxx.do`
    },
}

# 修改请求前参数

export default {
    paramsBeforeRequest: function (params) {
        // 此处可自定义调整请求前的参数
        // params.xxx = xxx
        return params
    },
}

注意

必须return修改完的参数params回去

# 启动分页

export default {
    // 默认为true: 开启
    isUsePagination: false // 关闭分页,一次性加载
}

# 获取列表后

export default {
    afterListJSON: function (data) {
        // do something for data
        // 操作完数据之后注意必须将数据返回return
        return data
    },
}

注意

必须return修改完的列表数据data回去

# 渲染列表后

export default {
    afterListRender: function (data) {
        console.log('列表渲染后需要执行的事件:afterListRender')
    },
}

# 是否隐藏搜索框

export default {
    // 默认为false,不隐藏
    // 若配置搜索框隐藏,则搜索过滤器也必然隐藏
    hideSearch: true, // 设置为隐藏
}

# 获取列表模型后

export default {
    // 获取列表模型后的回调事件,可更改模型数据
    afterModuleJSON: function (module) {
        module.remark = '获取编辑模型后的回调事件添加的数据'
        // 执行你的数据变更
        // do something change the module data
        // 注意:修改完之后必须将模型数据返回
        return module
    },
}

# 列表行自定义渲染

export default {
    // 列表行自定义渲染
    renderRow: {
        title: 'name',
        tag: {
            formatter (row) {
                if (String(row.status) === '1') {
                    return `<text class="dangerTag">${row.statusDesc}</text>`
                }
                return `<text class="primaryTag">${row.statusDesc}</text>`
            }
        },
        content: 'description',
        bottomTime: 'createTime'
    }
}

# 编辑js配置

# 按钮

默认按钮

// 编辑页面
[
    { id: 'back', name: '返回', icon: 'bd-back', type: 'danger', poritity: 5 },
    { id: 'save', name: '保存', icon: 'bd-save', type: 'primary', poritity: 10 },
]
// 查看页面
[
    { id: 'back', name: '返回', icon: 'bd-back', type: 'danger', poritity: 5 },
]
    1. 清空所有按钮
export default {
    buttons: [],
}
    1. 隐藏部分默认按钮
export default {
    buttons: [
        {
            id: 'save',
            /* 
                1. 直接赋值
                2. 支持函数
             */
            isHide: true,
            // isHide: () => true,
        }
    ]
}
    1. 更改默认按钮事件
export default {
    buttons: [
        {
            /** 按钮属性
             * 1. id: 必须、唯一
             * 2. name:按钮显示名称
             * 3. icon:按钮图标
             * 4. poritity:按钮排序号
             * 5. type: 按钮样式,可选值【primary、warning、danger、success、operate】
             * 6. position:按钮位置,可选值【right、row、page、pageBottom】;Array/String,可多选;默认值:['page']
             *      page:收缩在页面上
             *      row:点击行数据时会执行该按钮的事件;buttons中只能存在一个row;当itemClick存在时,会执行itemClick的内容,此参数无效
             *      right:单个行数据拥有按钮
             *      pageBottom:页面底部
             * 7. isMultiple:如果按钮可以多选,使用此方法,会先弹出行checkbox
             * 8. click:按钮点击事件
             * 备注:当id为【add、edit、view、delete】当中的某一个时,除id、click 外的其余属性非必填
             *      已有默认值(src/setting/frame-const.js文件中的listAttrs中有定义)
             */
            id: 'save',
            // name: '删除',
            // icon: 'bd-delete',
            // poritity: 40,
            // type: 'danger',
            click () {
                this.$message('我是自定义save事件!')
                let config = {
                    type: 'moduleEdit',
                    mdCode: 'goods_copy',
                    customSetting: {},
                    btnList: [{
                        id: 'save',
                        name: '确定',
                        click () {
                            this.validate().then(res => {
                                console.log(res)
                            })
                        }
                    }],
                }
                this.$showDialog(config)
            }
        }
    ],
}
    1. 添加默认按钮事件
export default {
    buttons: [
        /** 按钮属性
         * 1. id: 必须、唯一
         * 2. name:按钮显示名称
         * 3. icon:按钮图标
         * 4. poritity:按钮排序号
         * 5. type: 按钮样式,可选值【primary、warning、danger、success、operate】
         * 6. position:按钮位置,可选值【right、row、page、pageBottom】;Array/String,可多选;默认值:['page']
         *      page:收缩在页面上
         *      row:点击行数据时会执行该按钮的事件;buttons中只能存在一个row;当itemClick存在时,会执行itemClick的内容,此参数无效
         *      right:单个行数据拥有按钮
         *      pageBottom:页面底部
         * 7. isMultiple:如果按钮可以多选,使用此方法,会先弹出行checkbox
         * 8. click:按钮点击事件
         * 备注:当id为【add、edit、view、delete】当中的某一个时,除id、click 外的其余属性非必填
         *      已有默认值(src/setting/frame-const.js文件中的listAttrs中有定义)
         */
        {
            id: 'customBtn',
            name: '自定义',
            icon: 'bd-jsonFormat',
            type: 'success',
            click () {
                this.$message('我是自定义新增的按钮!')
            }
        }
    ],
}
    1. 支持使用priority进行按钮排序

说明

不使用priority字段将默认为999999,会排在通用按钮后面

框架默认按钮priority为以下:
    返回【back】:5
    关闭【close】:5
    保存【save】:10
ps:自定义修改按钮:
	1. 如果按钮id一致,没有定义priority属性,那么按照默认排序
    2. 如果按钮id一致,有定义priority属性,那么按照重新定义的priority的值进行排序
export default {
    buttons: [
        { 
            id: 'operateEvt',
            name: '操作',
            icon: 'bd-reset',
            type: 'primary',
            priority: 35,
            click: function (btnObj) {
                // do something
            }
        }, { 
            id: 'close', // 没有定义priority属性,priority 为默认值 5,
            name: '重写的关闭按钮',
            icon: 'bd-add',
            type: 'primary',
            click: function (btnObj) {
                // do something
            }
        }, { 
            id: 'save',
            name: '重写的保存按钮',
            icon: 'bd-save',
            type: 'primary',
            priority: 1, // 重新定义了priority属性,渲染时将会渲染在【新增按钮】按钮的前面
            click: function (btnObj) {
                // do something
            }
        },
    ],
}
    1. 使用函数,动态返回按钮数据(更加灵活)

注意

使用函数时,与直接传数组是存在差别的

  1. 直接传数组是相当于添加按钮,页面上会将原有按钮与这部分添加按钮进行合并
  2. 使用函数时,返回的按钮数据,页面上将直接使用此展示
export default {
    /**
     * @param {Array} defaultBtnList 默认的按钮列表数据
     */
    buttons: function (defaultBtnList) {
        // this:这里this指向为moduleList/index.vue页面所在作用域
        // 定义一条按钮数据
        let resetBtn = { 
            id: 'reset',
            name: '重置',
            icon: 'reset',
            type: 'warning',  // primary/warning/danger/success
            click: function (btnObj) {
                // btnObj: 当前按钮对象数据 {id:'reset', name...}
                // 定义获取列表选中数据
                let selection = this.getSelection()
                // 获取核心列表所在组件作用域,若列表需要刷新时调用
                let listPageRef = this.listPageRef()
                // 列表刷新
                listPageRef.init()
            }
        }
        // 在原有按钮组最前面添加一条按钮数据
        defaultBtnList.unshift(resetBtn)
        // 注意:必须return回去最终的按钮数组
        return defaultBtnList
    }
}

注意

函数最终必须将按钮结果数组return回去

    1. 仅在编辑页显示的按钮
export default {
    buttons: [
        {
            id: 'reset',
            name: '重置',
            icon: 'bd-reset',
            type: 'warning',
            priority: 40,
            isEdit: true,   // 仅在isView=false(编辑状态)的时候显示此按钮
            click () {
                // 点击事件
            }
        }
    ]
}
    1. 仅在查看页显示的按钮
export default {
    buttons: [
        {
            id: 'print',
            name: '打印',
            icon: 'bd-print',
            type: 'success',
            priority: 450,
            isView: true,   // 仅在isView=true(查看状态)的时候显示此按钮
            click () {
                // 点击事件
            }
        }
    ]
}

# 详情数据接口

export default {
    // 请求表单详情数据接口
    dataUrl () {
        return '/bbb'
    },
}

# 保存接口地址

export default {
    // 表单数据保存接口地址
    saveUrl () {
        return '/ccc'
    },
}

# 表单接口数据 - 字段值路径

export default {
    resPath: ''
}

示例

如接口返回数据格式如下

{
    bean: {
        data: {
            sex: 1,
            height: '189',
            name: '测试'
        }
    },
    hasOk: true,
    message: ''
}

resPath应配置resPath: 'bean,data',框架的默认配置为resPath: ''

# 获取详情-字段值路径

通用表单详情返回接口值

{
    sex: { value: 1 },
    height: { value: '174' },
    name: { value: '测试' }
}
则配置`valuePath: 'value'`,即默认获取`fieldObj["value"]`的字段值,此亦为框架默认配置值
export default {
    // 获取详情-字段值路径
    valuePath: '',
}

# 表单渲染前

export default {
    // 获取详情-字段值路径
    // valuePath: '',
    // 表单即将渲染前函数
    beforeRender (fieldList) {
        let field = fieldList.find(o => o.name === 'name')
        if (field) {
            field.value = '重新赋值'
        }
    },
}

# 字段验证规则

export default {
    // 字段验证规则
    validateRule () {
        return {
            richtextmuch: [
                { required: true, message: 'js添加的必填条件' },
                {
                    validateFunction (rule, value, data, callback) {
                        if (!value) {
                            // 验证通过,直接return true
                            return true
                        }
                        if (String(value) === '11') {
                            // 验证不通过,使用callback
                            callback('不能输入11')
                        }
                        return true
                    }
                }
            ]
        }
    },
}

# 字段值变更事件

export default {
    // 字段值变更事件
    valueChange: {
        name: function (formScope, fieldName, value, field) {
            if (value === '1') {
                let rules = [{ required: true, message: '值=1时添加必填' }]
                this.$set(field, 'rules', rules)
            }
        }
    }
}

# 表单子项尾端自定义渲染

export default {
    fieldAppend: {
        // 字段名称
        name: {
            formatter (field) {
                // 返回html字符串,使用原生标签,如div,span等
                return '<div style="color: red;">表单后缀</div>'
            },
            // formatter亦可直接为字符串
            // formatter: '<div>表单后缀2222</div>',
            click (field) {
                // 此后缀html的点击事件
            }
        }
    }
}