d2-crud-plus基操说明

d2-crud-plus的基本操作说明

相关文件api参考:http://greper.gitee.io/d2-crud-plus/guide/

colunms中的itemProps的class,名称为yxtInput我拿到了全局,不要在每个页面都加了,以后改的时候不好改。

之前封装的姓名,手机号,身份证号脱敏等全局方法还是 放在global.js里面。与之前的用法无异

1.1权限说明

菜单按钮的添加按照系统中的提示说明进行添加

按钮的权限在菜单相对应的页面中的操作列的按钮权限进行添加(一般是后台添加,除非个别修改前台进行修改)

1.2 页面说明(.vue页面)

页面中的基本的增删改查不需要做特别的设置,直接复制该目录下的vue页面:views/system/dictionary/index.vue。相关的操作方法不要做任何修改。除非在页面中又相关的审核等操作

1.3页面配置说明(crud.js)

配置文件的名称不要变动。详情见:views/system/dictionary/crud.js

pageOptions 是配置右上角相关的几种模式,具体见文档,常见设置如下:

pageOptions: {  //mxj 这是右上角的按钮显示
  compact: null, //mxj 是否显示紧凑模式传null,则不显示按钮
  search:null, //mxj 是否显示查询传null,则不显示按钮
  refresh:false,
  export:true,  //mxj 导出,配置完成之后需要在页面的crud-toolbar进行展示
},
 

options对应的el-table的设置,常见设置如下:

options: {
  tableType: 'vxe-table',
  rowKey: true, // 必须设置,true or false
  rowId: 'id',
  height: '100%', // 表格高度100%, 使用toolbar必须设置
  highlightCurrentRow: false,
  treeConfig: { // 树形数据配置
    children: 'children',
    hasChild: 'hasChildren',
    expandAll: true
  }
},
 

rowHandle对应的是表格的操作列,自定义的按钮方法在vue页面的<d2-crud-x @dictionaryConfigure="dictionaryConfigure"></d2-crud-x>上回传显示;如下:

// rowHandle:false,  //隐藏操作列
rowHandle: {
  width: 230,
  // dropdown: {  //mxj  ==>>操作按钮过多的时候设置的
  //   atLeast: 2, // 至少2个以上才收入下拉框中
  //   text: '更多'
  //  },
  view: {
    thin: true,
    text: '',
    // show(index, row) {return row.value == 'button_status_bool' },  //mxj==>>条件判断该操作按钮是否显示
    // disabled () {  //条件按钮是否显示
    //   return !vm.hasPermissions('Retrieve')
    // }
  },
  edit: {
    thin: true,
    text: '',
    disabled () {
      return !vm.hasPermissions('Update')
    }
  },
  //remove直接false删除按钮就不显示,
  remove: {
    thin: true,
    text: '',
    disabled () {
      return !vm.hasPermissions('Delete')
    }
  },
  //自定义按钮的配置  emit事件的回传是在d2-crud-x做@事件的方法
  custom: [{
    text: ' 字典配置',
    type: 'success',
    size: 'small',
    emit: 'dictionaryConfigure'
  }]
},
 

最重要的就是colums了,页面中相关的searchForm,addform,editform,viewform以及相关的table都在这里面进行配置,以下数组包含类型(input,select,radio,富文本编辑器,图片上传,tree的选择,时间选择器),包括全局字典的应用方法,colums列中的请求方法。

columns: [
    {
      title: '字典名称',
      // align:'center',  //mxj==>>对齐格式
      // show: false,  //mxj 是否显示在表格内
      key: 'label',
      search: {
        disabled: false,  //mxj 是否禁用该字段的查询,默认false  是否显示在搜索条件内,相对应的add ,form view等一样
        component: {  //mxj 查询框组件配置,默认根据form配置生成
          props: {  //mxj 查询 使用选择框组件,并且是可以清除的
            clearable: true
          }
        }
      },
      type: 'input', //mxj 字段类型
      // formatter (row, column, value, index) {  //mxj  脱敏展示,只展示在table中,相关的弹框展示原值
      //   return vm.$global.phoneNo(value)
      // },
      form: {
        rules: [ // 表单校验规则
          { required: true, message: '字典名称必填项' }
        ],
        component: {  ////添加和修改时form表单的组件
          props: {
            clearable: true, //mxj 可清除
          },
          placeholder: '请输入字典名称'
        },
        itemProps: { // mxj el-form-item的配置
          class: { yxtInput: true }   //mxj  yxtInput在相对应的添加和编辑的弹框的label的展示样式
        },
      }
    },
    {
      title: '编辑器内容',
      // align:'center',  //mxj==>>对齐格式
      key: 'editor',
      show: false,  //mxj  是否在列表中显示
      type: 'editor-wang', //mxj 字段类型
      search: {
        disabled: true,  //mxj 是否禁用该字段的查询,默认false
        component: {  //mxj 查询框组件配置,默认根据form配置生成
          props: {  //mxj 查询 使用选择框组件,并且是可以清除的
            clearable: true
          }
        }
      },
      form: {
        disabled: true,
        rules: [ // 表单校验规则
          { required: true, message: '字典名称必填项' }
        ],
        component: {  ////添加和修改时form表单的组件
          disabled: () => {
              return vm.getEditForm().disable
            },
            props: {
              index: 1, // 当同一个页面有多个editor时,需要配置不同的index
            },
          placeholder: '请输入内容'
        },
        itemProps: { // mxj el-form-item的配置
          class: { yxtInput: true }   //mxj  yxtInput在相对应的添加和编辑的弹框的label的展示样式
        },
      }
    },
    {
      title: '状态',
      key: 'status',
      width: 90,
      search: {
        disabled: false
      },
      type: 'radio',
      dict: {
        // data: [ // mxj  这是动态设置相关的select的数组值
        //       { value: 'menxiaojin', label: '深圳',color:'menxiaojin' },
        //       { value: 'false', label: '广州',color:'warning' },
        //     ],
        data: vm.dictionary('button_status_bool')    //mxj==>>vm.dictionary('button_status_bool')这是在下拉中全局字典的展示方式
      },
      form: {
        rules: [ // 表单校验规则
          { required: true, message: '状态必填项' }
        ],
        value: true,    //mxj
        component: {
          placeholder: '请选择状态'
        },
        itemProps: {
          class: { yxtInput: true }
        }
      },
    },
    {
      title: '时间搜索',
      key: 'sort1',
      type: 'datetimerange',
      show:false,
      labelWidth:300,
      search: {
        disabled: false,
        // width:'50%'
        component: {
          name: 'el-date-picker',
          props: {
          }
        }
      },
    },
{
        title: '成立时间',
        key: 'set_date',
        minWidth: 90,
        search: {
          disabled: true
        },
        type: 'date',
        form: {
          rules: [ // 表单校验规则
            {
              required: true,
              message: '成立时间必填'
            }
          ],
          component: {
            span: 12,
            placeholder: '请选择成立时间',
            props: { valueFormat: 'yyyy-MM-dd' }
          },
          itemProps: {
            class: { yxtInput: true }
          }
        }
      },
  {
        title: '上级党组织',
        key: 'status',
        width: 90,
        search: {
          disabled: true
        },
        type: 'select',
        dict: {
          cache: false,
          url: '/api/party/select/',
          value: 'id', // 数据字典中value字段的属性名
          label: 'name', // 数据字典中label字段的属性名
          getData: (url, dict, {
            form,
            component
          }) => {
            return request({
              url: url,
              // params: {
              //   page: 1,
              //   limit: 10
              // }
            }).then(ret => {
              // component._elProps.page = ret.data.page
              // component._elProps.limit = ret.data.limit
              // component._elProps.total = ret.data.total
              return ret.data
            })
          }
        },
        form: {
          component: {
            placeholder: '请选择上级党组织'
          },
        },
      },
        {  //mxj   这是点击弹出tree的框
        title: '部门',
        key: 'dept',
        search: {
          disabled: true
        },
        minWidth: 140,
        type: 'tree-selector',
        dict: {
          cache: true,
          isTree: true,
          url: '/api/system/dept/all_dept/',
          value: 'id', // 数据字典中value字段的属性名
          label: 'name' // 数据字典中label字段的属性名
        },
        form: {
          rules: [ // 表单校验规则
            {
              required: true,
              message: '必填项'
            }
          ],
          itemProps: {
            class: { yxtInput: true }
          },
          component: {
            span: 12,
            pagination: true,
            props: { multiple: false }
          }
        },
        component: {
          name: 'foreignKey',
          valueBinding: 'dept_name'
        }
      },
   {  //mxj  这是相关的图片上传,此处是头像单张,多图上传去文档搜素相对应的type类型
        title: '头像',
        key: 'avatar',
        type: 'avatar-uploader',
        width: 60,
        align: 'left',
        form: {
          component: {
            props: {
              elProps: { // 与el-uploader 配置一致
                multiple: false,
                limit: 1 // 限制5个文件
              },
              sizeLimit: 500 * 1024 // 不能超过限制
            },
            span: 24
          },
          helper: '限制文件大小不能超过500k'
        }
      }]
 

1.4可视化或者自定义页面的数据请求方法

vue页面方法。

相对应的组件引用的方法与我们之前的页面引用的方法一致。

<script>
import * as api from './api'

import threeDPie from "@/components/echarts/threeDPie.vue";

export default {
  name: 'workbench',
  components:{
    threeDPie
  },
  data () {
    return {

    }
  },
  methods: {

    initDemo(){
      api.GetList().then(res=>{
        console.log(res,'测试接口请求相关获取值')
      })
    },
  },
  mounted(){
    this.initDemo()
  },
}
</script>
 

api.js的页面展示

import { request } from '@/api/service'
export const urlPrefix = '/api/party/select/'

export function GetList (query) {
  return request({
    url: urlPrefix,
    method: 'get',
    params: { ...query }
  })
}
 

1.5表格或者按钮的自定义样式

相关字典展示文字的自定义状态修改如下

字典管理里面点击字典配置,在字典配置页面的标签颜色里做自定义设置。目录如下:views/system/dictionary/subDictionary/crud.js

{
        title: '标签颜色',
        key: 'color',
        width: 90,
        search: {
          disabled: true
        },
        type: 'select',
        dict: {
          //mxj ==>> 这里是自定义的颜色的值,然后在color.scss中进行颜色样式的设置等等
          data: [
            { label: 'menxiaojin', value: 'menxiaojin', color: 'menxiaojin' },
            { label: 'success', value: 'success', color: 'success' },
            { label: 'primary', value: 'primary', color: 'primary' },
            { label: 'info', value: 'info', color: 'info' },
            { label: 'danger', value: 'danger', color: 'danger' },
            { label: 'warning', value: 'warning', color: 'warning' }
          ]
        },
        form: {
          component: {
            props: {
              clearable: true
            }
          },
          itemProps: {
            class: { yxtInput: true }
          }
        }
      }
 

label是你自定义的颜色的展示名字,value和color是你自定义的颜色的class,相对应的class在src/assets/style/unit/color.scss里面做添加。如

.el-tag--menxiaojin{
    background: yellow;
    color: blue;
}
 

1.6表单内切换选项展示不同的内容

以下是做的demo展示,具体可根据实际情况进行展示。

{
  title: '表单内选项切换',
  key: 'change',
  sortable: false,
  type: 'radio',
  disabled: true,
  //mxj  要做的选项判断
  dict: { data: [{ value: 'one', label: '展示一' }, { value: 'two', label: '展示二' }] }
},
{
  title: '展示一',
  key: 'content1',
  type: 'input', // 富文本图片上传依赖file-uploader,请先配置好file-uploader
  disabled: true, // 设置true可以在行展示中隐藏
  form: {
    component: {
      span: 24,
      placeholder: '展示一呈现',
      show (context) {
        return context.form.change === 'one'
      }
    }
  }
},
{
  title: '展示二',
  key: 'content2',
  type: 'input', // 富文本图片上传依赖file-uploader,请先配置好file-uploader
  disabled: true, // 设置true可以在行展示中隐藏
  form: {
    component: {
      span: 24,
      placeholder: '展示二呈现',
      show (context) {   //mxj  这里根据form中要做判断的值进行呈现
        return context.form.change === 'two'
      }
    }
  }
},
 

1.7表单内新增分组(如投票选项类的添加)

demo展示。首先在vue页面添加下如下代码

<!-- 自定义测试 -->
<template slot="topicsFormSlot" slot-scope="scope">
  <el-input :disabled="scope.mode==='view'" class="d2-mb-5" v-for="(item,index) in scope.form.topics" :key="index"
    v-model="scope.form.topics[index]" placeholder="请输入内容">
    <el-button :disabled="scope.mode==='view'" slot="append" icon="el-icon-remove-outline" @click="removeTopic(index)"/>
  </el-input>
  <el-button :disabled="scope.mode==='view'" @click="addTopic">新增选项</el-button>
</template>
 

在methods中添加方法:

//ceshi
addTopic () {
  const form = this.getEditForm()
  console.log('form:', form)
  if (form.topics == null || form.topics === '') {
    form.topics = []
  }
  form.topics.push('')
},
removeTopic (index) {
  const form = this.getEditForm()
  console.log('form:', form)
  form.topics.splice(index, 1)
},
 

在crud.js的colunms添加如下

{
  title: '新增选项',
  key: 'topics',
  type: 'select',
  form: {
    component: {
      span: 24,
    },
    slot: true
  }
},
 

1.8table的设置的序号的修改

页面中原始的indexRow序号不会随着页面的递增而递增,所以我们需要在colums中设置序号进行展示,原始的index Row注释掉,代码如下:

// indexRow: {
//   // 或者直接传true,不显示title,不居中
//   title: "序号1",
//   align: "center",
//   width: 80,
//   renderHeader:'123'
// },
columns: [
  //序号展示
  {
    title: "序号",
    key: "xuhao",
    disabled: false,
    form: {
      disabled: true,
    },
    width:80,
    align:'center',
    formatter(row, column, cellValue, index){
      var index = (vm.crud.pagination.currentPage-1)*vm.crud.pagination.pageSize+index+1
      return index
    }
  },
 ]
 

1.9 图片展示

此框架中图片上部上传半路径,前端展示的时候进行判断拼接展示全路径,具体方法如下:

{
  title: '头像',
  // key: 'avatar',  //原图片字段
  key:'cusAvatar',  //自定义图片字段进行展示
  type: 'avatar-uploader',
  width: 60,
  align: 'left',
  //进行图片的展示
  valueBuilder (row, key) {
      row.cusAvatar = vm.$global.imgPross(row.avatar)
  },
  //编辑上传进行图片的回传
  valueResolve (row, key) {
    row.avatar = row.cusAvatar
  },
  form: {
    component: {
      props: {
        elProps: { // 与el-uploader 配置一致
          multiple: false,
          limit: 1 // 限制5个文件
        },
        sizeLimit: 500 * 1024, // 不能超过限制
        //半路径展示全路径展示,此处设置valueType为key,然后用buildUrl进行拼接展示
        valueType: 'key',
        buildUrl (value, item) {
          return vm.$global.imgPross(value)
          // 私有下载链接,在后端构建cos签名后的url,然后redirect到该地址进行下载
        }
      },
      span: 24
    },
    helper: '限制文件大小不能超过500k'
  }
}
 

1.10数据联动的问题

如果相关配置想需要在搜索表单中进行展示联动,那么需要配置如下代码

searchOptions: {
  valueChange: true // 搜索框开启valueChange
},
 

colums中的具体的配置

{
  title: "小区",
  key: "uptown",
  align: "center",
  search: { disabled: false },
  type: "select",
  dict: {
    cache: false,
    url: "/api/uptown/select/",
    value: "id",
    label: "label",
    getData: (url, dict, { form, component }) => {
      return request({
        url: url,
      }).then((ret) => {
        return ret.data;
      });
    },
  },
  form: {
    component: {
      placeholder: "请选择小区",
    },
    valueChange (key, value, form, { getColumn, mode, component, immediate, getComponent }) {
      form.building = undefined  //置空
      if (value) {
        getComponent('building').reloadDict() // 执行city的select组件的reloadDict()方法,触发“building”重新加载字典

      }
    },
    // valueChangeImmediate: false // 是否在编辑框打开后立即触发一次valueChange方法
  },
},
{
  title: "楼栋单元",
  key: "building",
  align: "center",
  search: { disabled: false },
  type: "select",
  dict: {
    url (dict, { form /* 当前的form表单 */, component /* 当前的组件ref */ }) {
      console.log('===>>>',form)
      if (form && form.uptown != null) { // 本数据字典的url是通过前一个select的选项决定的
        return '/api/uptown/building/select/?uptown=' + form.uptown+'&type=2'
      }
      return undefined // 返回undefined 将不加载字典
    },
    immediate: true,
    value: 'id',
    label: "label",
  },
  form: {
    component: {
      placeholder: "请选择楼栋单元",
      props: { dict: { cache: false } }
    },
    valueChange (key, value) {

      // console.log('您选择了:', value)
    }
  },
},
 

1.11 菜单管理

PS:测试环境的菜单可以自由配置,但是正式环境的菜单需要售前出具菜单表格,在平台管理页面去分配,即第3条

目前crud 框架的菜单现在用的是同一个数据库(也就是一套菜单);智慧社区类的功能基本上都一样,除了定制化功能。相关的街道 社区 小区的账号也可以在同一项目中做不通的展示,根据权限控制做展示,不需要在单独部署平台;

  1. 项目创建完成,原有的功能按照既定的路由进行做展示,不要修改!!!新功能在创建菜单的时候一定要把这个页面所用到的接口权限加上(即菜单按钮页面),同时也要把菜单排序写好(从小到大依次排序);
  2. 创建账号,建立账号时一定要明确这个账号的角色权限;因为所有的账号权限都是通过角色管理来分配的。

通过总的管理员账号,在平台管理页面去分配各个平台管理员所需要的页面,(这时可以自由调整目录接口,修改目录,菜单的名称,这里指的是正式环境);

各个平台管理员账号的权限分配好了之后,用各个平台管理员账号登录自己的平台(利津管理员账号登录利津平台),这个时候再去创建自己平台的账号,然后从角色管理页面分配权限等。
后续会继续补充


1.11 部分公共方法和css的整理与说明


    1. 公共方法全部封装在global.js,(例如:姓名,手机号,身份证号脱敏等等);
    2. 页面中的echarts图表也做了封装,全都在src/components/echarts 目录下(例如;饼图,柱状图,玫瑰图等等);
    3. 页面中三级联动筛选的组件在 src/components/topAreaChoose 目录下面(区县,街道,社区);
    4.  color.scss自定义的颜色的样式( 在src/assets/style/unit 目录下)
    5. public-assembly.scss(src/assets/style/public-assembly.scss)是页面中统计图的背景和高度,form表单的样式重置,列表的查询 重置 按钮,弹窗,列表,表格页脚等等;
    6. public-common.scss(src/assets/style/public-common.scss)公共的css样式(margin  padding font-size,height.weight,定位,超出隐藏,flex布局,白色字体,float浮动等);

 

posted @ 2026-01-29 10:57  星宝攸宁  阅读(4)  评论(0)    收藏  举报