sr před 4 roky
rodič
revize
2f8da27e59

+ 4 - 3
ruoyi-ui/package.json

@@ -38,7 +38,7 @@
   "dependencies": {
     "@riophae/vue-treeselect": "0.4.0",
     "axios": "0.21.0",
-    "burgeon-ui": "^1.0.56",
+    "burgeon-ui": "^1.0.46",
     "clipboard": "2.0.6",
     "core-js": "3.8.1",
     "echarts": "4.9.0",
@@ -49,6 +49,8 @@
     "js-beautify": "1.13.0",
     "js-cookie": "2.2.1",
     "jsencrypt": "3.0.0-rc.1",
+    "less": "^4.1.1",
+    "less-loader": "^4.1.0",
     "nprogress": "0.2.0",
     "quill": "1.3.7",
     "screenfull": "5.0.2",
@@ -58,8 +60,7 @@
     "vue-cropper": "0.5.5",
     "vue-router": "3.4.9",
     "vuedraggable": "2.24.3",
-    "vuex": "3.6.0",
-    "burgeon-ui": "1.0.46"
+    "vuex": "3.6.0"
   },
   "devDependencies": {
     "@vue/cli-plugin-babel": "4.4.6",

+ 83 - 0
ruoyi-ui/src/api/modeler.js

@@ -11,3 +11,86 @@ export const getSearch = (data) => {
     data
   })
 }
+export const setMigrate = (data) => {
+  return request({
+    headers: {
+      'accountName': 'guest'
+    },
+    url: '/jflow/p/cs/module/migrate',
+    method: 'post',
+    data
+  })
+}
+// 发布流程
+export const setPublish = (data) => {
+  return request({
+    headers: {
+      'accountName': 'guest'
+    },
+    url: '/jflow/p/cs/module/publish',
+    method: 'post',
+    data
+  })
+}
+//停用流程
+export const setUnpublish = (data) => {
+  return request({
+    headers: {
+      'accountName': 'guest'
+    },
+    url: '/jflow/p/cs/module/unpublish',
+    method: 'post',
+    data
+  })
+}
+//复制流程
+export const setCopy = (data) => {
+  return request({
+    headers: {
+      'accountName': 'guest'
+    },
+    url: '/jflow/p/cs/module/copy',
+    method: 'post',
+    data
+  })
+}
+export const getLoad = (data) => {
+  return request({
+    headers: {
+      'accountName': 'guest'
+    },
+    url: '/jflow/p/cs/module/load',
+    method: 'post',
+    data
+  })
+}
+export const getDuplicate = (data) => {
+  return request({
+    headers: {
+      'accountName': 'guest'
+    },
+    url: '/jflow/p/cs/module/duplicate',
+    method: 'post',
+    data
+  })
+}
+export const getCommit = (data) => {
+  return request({
+    headers: {
+      'accountName': 'guest'
+    },
+    url: '/jflow/p/cs/module/commit',
+    method: 'post',
+    data
+  })
+}
+export const getPublish = (data) => {
+  return request({
+    headers: {
+      'accountName': 'guest'
+    },
+    url: '/jflow/p/cs/module/publish',
+    method: 'post',
+    data
+  })
+}

+ 9 - 0
ruoyi-ui/src/api/system/role.js

@@ -16,6 +16,15 @@ export function getRole(id) {
     method: 'get'
   })
 }
+
+// 保存
+export function setMenu(data) {
+  return request({
+    url: '/boman-system/role/menu',
+    method: 'post',
+    data: data
+  })
+}
 
 // 新增角色
 export function addRole(data) {

+ 238 - 0
ruoyi-ui/src/assets/styles/theme.scss

@@ -0,0 +1,238 @@
+@import '../../../node_modules/burgeon-ui/src/styles/index.scss';
+
+
+//接收主题参数,设置变量
+  // Prefix
+
+  // Color
+  @primary-color          : rgba(91, 133, 228, 1);
+  @info-color             : #2db7f5;
+  @success-color          : #19be6b;
+  @processing-color       : @primary-color;
+  @warning-color          : #ff9900;
+  @error-color            : #ed4014;
+  @normal-color           : #e6ebf1;
+  @link-color             : #2D8cF0;  //a链接
+  @link-hover-color       : tint(@link-color, 20%);
+  @link-active-color      : shade(@link-color, 5%);
+  @selected-color         : fade(@primary-color, 90%);
+  @tooltip-color          : #fff;
+  @subsidiary-color       : #808695;
+  @rate-star-color        : #f5a623;
+
+  // Base
+  @body-background        : #fff;
+  @font-family            : "Microsoft YaHei",Helvetica,"PingFang SC","Hiragino Sans GB","Microsoft YaHei","微软雅黑",Arial,sans-serif;
+  @code-family            : Consolas,Menlo,Courier,monospace;
+  @title-color            : #666;
+  @text-color             : rgba(87, 87, 87, 1);
+  @font-size-base         : 12px;
+  @font-size-small        : 12px;
+  @font-size-large        : 16px;
+  @line-height-base       : 1;
+  @line-height-computed   : floor((@font-size-base * @line-height-base));
+  @border-radius-base     : 6px;
+  @border-radius-small    : 4px;
+  @cursor-disabled        : not-allowed;
+  @modal-radius-base      : 6px;
+  @modal-pos-radius-base      : 6px;
+  @modal-mask-background: rgba(0, 0, 0, 0.3);
+
+
+  @table-height-base: 27px;  //表行高
+  @table-th-height-base: 27px;//表头行高
+  @table-padding-base:8px;  //cell的padding值
+
+
+
+  // Border 配置
+  @border-color-base      : #dcdee2;  // outside
+  @border-color-split     : #e8eaec;  // inside
+  @border-width-base      : 1px;            // width of the border for a component
+  @border-style-base      : solid;          // style of a components border
+
+  // Background color
+  @background-color-base        : #f7f7f7;  // 全局背景色
+  @background-color-select-hover: @input-disabled-bg;  //默认选中背景颜色
+  @tooltip-bg                   : rgba(70, 76, 91, .9);
+  @head-bg                      : #f9fafc;
+  @table-thead-bg               : #f5f6fa;//表头背景色
+  @table-td-stripe-bg           : #f8f8f9;//斑马线颜色
+  @table-td-hover-bg            : rgba(235, 247, 255, 1);//hover颜色
+  @table-td-highlight-bg        : rgba(235, 247, 255, 1);//选中色
+  @menu-dark-title              : rgba(60, 63, 71, 1);
+  @menu-dark-active-bg          : rgba(47, 48, 52, 1);
+  @menu-dark-subsidiary-color   : rgba(255,255,255);  //菜单主题为menu时的文字颜色
+  @menu-dark-group-title-color  : rgba(255,255,255,.36);
+  @date-picker-cell-hover-bg    : #e1f0fe;
+
+  // Shadow
+  @shadow-color           : rgba(0, 0, 0, .2);
+  @shadow-base            : @shadow-down;
+  @shadow-card            : 0 1px 1px 0 rgba(0,0,0,.1);
+  @shadow-up              : 0 -1px 6px @shadow-color;
+  @shadow-down            : 0 1px 6px @shadow-color;
+  @shadow-left            : -1px 0 6px @shadow-color;
+  @shadow-right           : 1px 0 6px @shadow-color;
+
+  // Button
+  @btn-font-weight        : normal;
+  @btn-padding-base       : 8px 21px;
+  @btn-padding-large      : 6px 15px 6px 15px;
+  @btn-padding-small      : 1px 7px 2px;
+  @btn-padding-base-icon  : 5px 15px 6px;
+  @btn-padding-large-icon : 6px 15px 6px 15px;
+  @btn-padding-small-icon : 1px 7px 2px;
+  @btn-font-size          : 12px;
+  @btn-font-size-large    : 14px;
+  @btn-border-radius      : 4px;
+  @btn-border-radius-small: 3px;
+  @btn-group-border       : shade(@primary-color, 5%);
+
+
+  //按钮禁用样式
+  @btn-disable-color      : #D8D8D8;
+  @btn-disable-bg         : #F4F4F4;
+  @btn-disable-border     : #D8D8D8;
+
+  @btn-default-color      : @text-color;
+  @btn-default-bg         : #fff;
+  @btn-default-border     : @border-color-base;
+
+  //fc default button
+  @btn-fcdefault-color: @primary-color;
+  @btn-fcdefault-bg         : #fff;
+  @btn-fcdefault-border     : @primary-color;
+  @btn-fcdefault-disabled     : #D8D8D8 ;
+  @btn-fcdefault-disabled-bg     : #F4F4F4 ;
+  @btn-fcdefault-disabled-color:#D8D8D8;
+  @btn-fcdefault-width:50px;
+
+  //pos default button
+  @btn-posdefault-color: #fff;
+  @btn-posdefault-bg         : @primary-color;
+  @btn-posdefault-border     : @btn-posdefault-bg  ;
+  @btn-posdefault-hover-bg     : @primary-color;
+  @btn-posdefault-disabled     : #D8D8D8 ;
+  @btn-posdefault-disabled-bg     : #F4F4F4;
+  @btn-posdefault-disabled-color:#D8D8D8;
+
+  @btn-primary-color      : #fff;
+  @btn-primary-bg         : @primary-color;
+
+  @btn-ghost-color        : @text-color;
+  @btn-ghost-bg           : #fff;
+  @btn-ghost-border       : @border-color-base;
+
+  @btn-circle-size        : 28px;  //分页按钮大小
+  @btn-circle-size-large  : 36px;
+  @btn-circle-size-small  : 24px;
+
+  // Layout and grid
+  @grid-columns                : 24;
+  @grid-gutter-width           : 0;
+  @layout-body-background      : #f5f7f9;
+  @layout-header-background    : #515a6e;
+  @layout-header-height        : 64px;
+  @layout-header-padding       : 0 50px;
+  @layout-footer-padding       : 24px 50px;
+  @layout-footer-background    : @layout-body-background;
+  @layout-sider-background     : @layout-header-background;
+  @layout-trigger-height       : 48px;
+  @layout-trigger-color        : #fff;
+  @layout-zero-trigger-width   : 36px;
+  @layout-zero-trigger-height  : 42px;
+
+  // Legend   关闭按钮icon颜色
+  @legend-color           : #999;
+
+  // Input
+  @input-height-base           : 32px;
+  @input-height-large          : 36px;
+  @input-height-small          : 24px;
+
+  @input-padding-horizontal    : 10px;  //输入框左右padding
+  @input-padding-vertical-base : 5px; //输入框上下padding
+  @input-padding-vertical-small: 1px;
+  @input-padding-vertical-large: 6px;
+
+
+  @input-placeholder-color     : #aaa;
+  @input-color                 : @text-color;
+  @input-disabled-color        : @text-color;
+  @input-border-radius         : 2px;
+  @input-border-color          : rgba(216, 216, 216, 1);
+  @input-bg                    : #fff;
+  @input-group-bg              : #f8f8f9;
+
+  @input-hover-border-color    : rgba(15, 142, 233, 1);
+  @input-focus-border-color    : rgba(15, 142, 233, 1);
+  @input-disabled-bg           : rgba(244, 244, 244, 1);
+
+  // Tag
+  @tag-font-size          : 12px;
+
+  // Media queries breakpoints
+  // Extra small screen / phone
+  @screen-xs              : 480px;
+  @screen-xs-min          : @screen-xs;
+  @screen-xs-max          : (@screen-xs-min - 1);
+
+  // Small screen / tablet
+  @screen-sm              : 768px;
+  @screen-sm-min          : @screen-sm;
+  @screen-sm-max          : (@screen-sm-min - 1);
+
+  // Medium screen / desktop
+  @screen-md              : 992px;
+  @screen-md-min          : @screen-md;
+  @screen-md-max          : (@screen-md-min - 1);
+
+  // Large screen / wide desktop
+  @screen-lg              : 1200px;
+  @screen-lg-min          : @screen-lg;
+  @screen-lg-max          : (@screen-lg-min - 1);
+
+  // Z-index
+  @zindex-spin            : 8;
+  @zindex-affix           : 10;
+  @zindex-back-top        : 10;
+  @zindex-select          : 900;
+  @zindex-modal           : 1000;
+  @zindex-drawer          : 1000;
+  @zindex-message         : 1010;
+  @zindex-notification    : 1010;
+  @zindex-tooltip         : 1060;
+  @zindex-transfer        : 1060;
+  @zindex-loading-bar     : 2000;
+  @zindex-spin-fullscreen : 2010;
+
+  // Animation
+  @animation-time         : .3s;
+  @transition-time        : .2s;
+  @ease-in-out            : ease-in-out;
+
+  // Slider
+  @slider-color              : tint(@primary-color, 20%);
+  @slider-height             : 4px;
+  @slider-margin             : 16px 0;
+  @slider-button-wrap-size   : 18px;
+  @slider-button-wrap-offset : -4px;
+  @slider-disabled-color     : #ccc;
+
+  // Avatar
+  @avatar-size-base: 32px;
+  @avatar-size-lg: 40px;
+  @avatar-size-sm: 24px;
+  @avatar-font-size-base: 18px;
+  @avatar-font-size-lg: 24px;
+  @avatar-font-size-sm: 14px;
+  @avatar-bg: #ccc;
+  @avatar-color: #fff;
+  @avatar-border-radius: @border-radius-small;
+
+  // Anchor
+  @anchor-border-width: 2px;
+
+  //icon 字体大小
+  @icon-font:16px;

+ 0 - 1
ruoyi-ui/src/components/FormItemComponent/index.vue

@@ -57,7 +57,6 @@ export default {
     // 通过layoutAlgorithm算法得到对应的位置坐标
     dataColRol() {
       const list = layoutAlgorithm(this.defaultColumn, this.currentFormList);
-      console.log(list,88111111)
       return Object.keys(list).reduce((temp, current) => {
         // 计算显示行数
         list[current].component = Vue.extend(list[current].component);

+ 18 - 6
ruoyi-ui/src/components/listModalComponent/index.vue

@@ -36,6 +36,11 @@
 <script>
 import {DispatchEvent} from '@/utils/dispatchEvent.js'
 import {  mapMutations } from 'vuex';
+import {
+    setPublish,
+    setUnpublish,
+    setCopy,
+  } from '@/api/modeler.js'
 export default {
   name:'listModalComponent',
   props:{
@@ -103,7 +108,7 @@ export default {
     },
     releaseProcess () {  //发布流程
       this.$refs.poptip.handleClose()
-      this.$network.post('/p/cs/module/publish', {id:this.items.id}).then((res) => {
+      setPublish({id:this.items.id}).then((res) => {
         if(typeof this.items.event.queryLists === 'function'){
           this.items.event.queryLists()
         }
@@ -112,7 +117,7 @@ export default {
     editingProcess () { //编辑流程
       this.$refs.poptip.handleClose()
       this.changeKeepAliveArray(['TemplateManagementLists'])
-      this.$router.push({ path: `/TemplateManagementNew/${this.items.id}` })
+      this.$router.push({ path: `/tool/activiti/TemplateManagementNew/${this.items.id}` })
       this.currentChange({
         path:'/TemplateManagementLists'
       });
@@ -127,7 +132,7 @@ export default {
     },
     stopProcess () {  //停用流程
       this.$refs.poptip.handleClose()
-      this.$network.post('/p/cs/module/unpublish', {id:this.items.id}).then((res) => {
+      setUnpublish({id:this.items.id}).then((res) => {
         if(typeof this.items.event.queryLists === 'function'){
           this.items.event.queryLists()
         }
@@ -135,20 +140,27 @@ export default {
     },
     copyProcess () {  //复制流程
       this.$refs.poptip.handleClose()
-      this.$network.post('/p/cs/module/copy', {id:this.items.id}).then((res) => {
-        if(res.data.resultCode === 0){
+      setCopy({id:this.items.id}).then((res) => {
+        if(res.resultCode === 0){
           this.changeKeepAliveArray(['TemplateManagementLists'])
           this.$router.push({ path: `/TemplateManagementNew/${res.data.data.id}` })
           this.currentChange({
             path:'/TemplateManagementLists'
           });
+        }else{
+          this.$Modal.fcError({
+            title:'错误',
+            content:res.resultMsg,
+            onOk: () => {
+            }
+          })
         }
       })
     },
     previewProcess () { //预览流程
       this.$refs.poptip.handleClose()
       this.changeKeepAliveArray(['TemplateManagementLists'])
-      this.$router.push({ path: `/TemplateManagementNew/${this.items.id}/1` })
+      this.$router.push({ path: `/tool/activiti/TemplateManagementNew/${this.items.id}/1` })
       this.currentChange({
         path:'/TemplateManagementLists'
       });

+ 321 - 0
ruoyi-ui/src/config/props.config.js

@@ -0,0 +1,321 @@
+// 输入框
+const input = {
+  // item 类型
+  type: 'input', // 必填!
+  // label名称
+  title: '', // 必填!
+  // 字段名称
+  field: '', // 必填!
+  // input值
+  value: '',
+  props: {
+    // 输入框类型,可选值为 text、password、textarea、url、email、date
+    type: 'text', // 必填!
+    // 是否显示清空按钮
+    clearable: false,
+    // 设置输入框为禁用状态
+    disabled: false,
+    // 设置输入框为只读
+    readonly: false,
+    // 文本域默认行数,仅在 textarea 类型下有效
+    rows: 4,
+    // 自适应内容高度,仅在 textarea 类型下有效,可传入对象,如 { minRows: 2, maxRows: 6 }
+    autosize: false,
+    // 将用户的输入转换为 Number 类型。在有正则的时候:1)该输入框为空的时候,值为空字符串。2)input方法不可用。
+    number: false,
+    // 自动获取焦点
+    autofocus: false,
+    // 原生的自动完成功能,可选值为 off 和 on
+    autocomplete: 'off',
+    // 占位文本
+    placeholder: '请输入',
+    // 输入框尺寸,可选值为large、small、default或者不设置
+    size: 'default',
+    // 最大输入长度
+    maxlength: null,
+    // 输入框尾部图标,仅在 text 类型下有效
+    icon: null,
+    // 输入框头部图标
+    prefix: null,
+    // 输入框尾部图标
+    suffix: null,
+    // 给表单元素设置 id,详见 Form 用法。
+    'element-id': null,
+    // 原生的 spellcheck 属性
+    spellcheck: false,
+    // 原生的 wrap 属性,可选值为 hard 和 soft,仅在 textarea 下生效
+    wrap: 'soft',
+    // 正则表达式
+    regx: null
+  },
+  event: {
+    // 按下回车键时触发
+    enter: (event, $this) => {},
+    // 设置 icon 属性后,点击图标时触发
+    click: (event, $this) => {},
+    // 数据改变时触发
+    change: (event, $this) => {},
+    // 输入框聚焦时触发
+    focus: (event, $this) => {},
+    // 输入框失去焦点时触发
+    blur: (event, $this) => {},
+    // 原生的 keyup 事件
+    keyup: (event, $this) => {},
+    // 原生的 keydown 事件
+    keydown: (event, $this) => {},
+    // 原生的 keypress 事件
+    keypress: (event, $this) => {},
+    // 开启 search 时可用,点击搜索或按下回车键时触发
+    search: (event, $this) => {},
+    // 添加正则后,校验出错的时候触发
+    regxCheck: (value, $this, errorValue) => {}
+  },
+};
+// 下拉框
+const select = {
+  type: 'select', // 必填!
+  // label名称
+  title: '', // 必填!
+  // 字段名称
+  field: '', // 必填!
+  // input值
+  value: '',
+  // 可选参数
+  options: [
+    // { value: '104', label: '生态蔬菜', disabled: false },
+    // { value: '105', label: '新鲜水果', disabled: false },
+  ],
+  props: {
+    // 是否支持多选
+    multiple: false,
+    // 多选情况下的样式控制,只在multiple为true有效
+    multipleType: false,
+    // 是否禁用
+    disabled: false,
+    // 是否可以清空选项,只在单选时有效
+    clearable: true,
+    // 选择框大小,可选值为large、small、default或者不填
+    size: 'default',
+    // 选择框默认文字
+    placeholder: '请选择',
+    // 当下拉列表为空时显示的内容
+    'not-found-text': '无匹配数据',
+    // 在返回选项时,是否将 label 和 value 一并返回,默认只返回 value
+    'label-in-value': false,
+    // 弹窗的展开方向,可选值为 bottom 和 top
+    placement: 'bottom',
+    // 是否将弹层放置于 body 内,在 Tabs、带有 fixed 的 Table 列内使用时,建议添加此属性,它将不受父级样式影响,从而达到更好的效果
+    transfer: true,
+  }
+};
+// Switch
+const Switch = {
+  type: 'Switch', // 必填!
+  // label名称
+  title: '', // 必填!
+  // 字段名称
+  field: '', // 必填!
+  // input值
+  value: false,
+  props: {
+    
+  }
+};
+// 单选框
+const radiobox = {
+  type: 'radiobox', // 必填!
+  // label名称
+  title: '', // 必填!
+  // 字段名称
+  field: '', // 必填!
+  // input值
+  value: false,
+  // 可选参数
+  props: {
+    // 多选框组的尺寸,可选值为 large、small、default 或者不设置
+    size: 'default',
+    // 是否禁用当前项
+    disabled: false
+  }
+};
+// 复选框
+const checkbox = {
+  type: 'checkbox', // 必填!
+  // label名称
+  title: '', // 必填!
+  // 字段名称
+  field: '', // 必填!
+  // input值
+  value: false,
+  // 可选参数
+  props: {
+    // 多选框组的尺寸,可选值为 large、small、default 或者不设置
+    size: 'default',
+    // 是否禁用当前项
+    disabled: false,
+    // 支持checkout样式为radio样式
+    circle: false
+  },
+  event: {
+    change: (event, $this) => {},
+  }
+};
+// 日期选择
+const DatePicker = {
+  type: 'DatePicker', // 必填!
+  field: '', // 必填!
+  title: '活动日期', // 必填!
+  // input值, type为daterange,datetimerange value为数组 [start_value,end_value]
+  value: '',
+  props: {
+    // 显示类型,可选值为 date、daterange、datetime、datetimerange、year、month
+    type: 'datetimerange', // 必填!
+    // 展示的日期格式
+    format: 'yyyy-MM-dd HH:mm',
+    // 日期选择器出现的位置,可选值为toptop-starttop-endbottombottom-startbottom-endleftleft-startleft-endrightright-startright-end
+    placement: 'bottom-start',
+    // 占位文本
+    placeholder: '请选择获得时间',
+    // 选择器额外配置,比如不可选日期与快捷选项
+    options: {
+      disabledDate (date) {
+          return date && date.valueOf() > Date.now();
+      }
+    },
+    // 手动控制日期选择器的显示状态,true 为显示,false 为收起。使用该属性后,选择器不会主动关闭。建议配合 slot 及 confirm 和相关事件一起使用
+    open: null,
+    // 是否显示底部控制栏,开启后,选择完日期,选择器不会主动关闭,需用户确认后才可关闭
+    confirm: false,
+    // 尺寸,可选值为large、small、default或者不设置
+    size: 'default',
+    // 是否禁用选择器
+    disabled: false,
+    // 是否显示清除按钮
+    clearable: true,
+    // 完全只读,开启后不会弹出选择器
+    readonly: false,
+    // 文本框是否可以输入
+    editable: false,
+    // 是否将弹层放置于 body 内,在 Tabs、带有 fixed 的 Table 列内使用时,建议添加此属性,它将不受父级样式影响,从而达到更好的效果
+    transfer: true
+  }
+};
+
+// 下拉框
+const DropDownSelectFilter = {
+  type: 'DropDownSelectFilter', // 必填!
+  field: '', // 必填!
+  title: '', // 必填!
+  value: '',
+  props: {
+    placeholder:'请选择',
+    // 是否是单选,可选值为 true、false
+    single: true,
+    // 下拉气泡表格里数据
+    data: {},
+    // 数据总条数
+    totalRowCount: 0,
+    // 每页条数
+    pageSize: 10,
+    // 模糊搜索的数据
+    AutoData: [],
+    // 模糊搜索要显示的列
+    columns: [],
+    // 无数据的时候提示
+    dataEmptyMessage: '暂无数据',
+    // 下拉多选 默认选中数据
+    defaultSelected: [],
+    // 是否将弹层放置于 body 内
+    transfer: true,
+    columnsKey:[]
+  }
+};
+//下拉和输入框混合
+
+const selectInput = {
+  // item 类型
+  type: 'selectInput', // 必填!
+  // label名称
+  title: '', // 必填!
+  // 字段名称
+  field: '', // 必填!
+  // input值
+  value: '',
+  slotfiled:'',//卡槽对应的键
+  slotValue:'', 
+  props: {
+    // 输入框类型,可选值为 text、password、textarea、url、email、date
+    type: 'text', // 必填!
+    // 是否显示清空按钮
+    clearable: false,
+    // 设置输入框为禁用状态
+    disabled: false,
+    // 设置输入框为只读
+    readonly: false,
+    // 文本域默认行数,仅在 textarea 类型下有效
+    rows: 4,
+    // 自适应内容高度,仅在 textarea 类型下有效,可传入对象,如 { minRows: 2, maxRows: 6 }
+    autosize: false,
+    // 将用户的输入转换为 Number 类型。在有正则的时候:1)该输入框为空的时候,值为空字符串。2)input方法不可用。
+    number: false,
+    // 自动获取焦点
+    autofocus: false,
+    // 原生的自动完成功能,可选值为 off 和 on
+    autocomplete: 'off',
+    // 占位文本
+    placeholder: '请输入',
+    // 输入框尺寸,可选值为large、small、default或者不设置
+    size: 'default',
+    // 最大输入长度
+    maxlength: null,
+    // 输入框尾部图标,仅在 text 类型下有效
+    icon: null,
+    // 输入框头部图标
+    prefix: null,
+    // 输入框尾部图标
+    suffix: null,
+    // 给表单元素设置 id,详见 Form 用法。
+    'element-id': null,
+    // 原生的 spellcheck 属性
+    spellcheck: false,
+    // 原生的 wrap 属性,可选值为 hard 和 soft,仅在 textarea 下生效
+    wrap: 'soft',
+    // 正则表达式
+    regx: null
+  },
+  event: {
+    // 按下回车键时触发
+    enter: (event, $this) => {},
+    // 设置 icon 属性后,点击图标时触发
+    click: (event, $this) => {},
+    // 数据改变时触发
+    change: (event, $this) => {},
+    // 输入框聚焦时触发
+    focus: (event, $this) => {},
+    // 输入框失去焦点时触发
+    blur: (event, $this) => {},
+    // 原生的 keyup 事件
+    keyup: (event, $this) => {},
+    // 原生的 keydown 事件
+    keydown: (event, $this) => {},
+    // 原生的 keypress 事件
+    keypress: (event, $this) => {},
+    // 开启 search 时可用,点击搜索或按下回车键时触发
+    search: (event, $this) => {},
+    // 添加正则后,校验出错的时候触发
+    regxCheck: (value, $this, errorValue) => {}
+  },
+};
+
+
+const dataProp = {
+  DatePicker,
+  checkbox,
+  radiobox,
+  Switch,
+  select,
+  input,
+  selectInput,
+  DropDownSelectFilter
+};
+export default dataProp;

+ 5 - 1
ruoyi-ui/src/main.js

@@ -1,6 +1,10 @@
 import Vue from 'vue'
 
-import Cookies from 'js-cookie'
+import Cookies from 'js-cookie'
+
+// import '@/assets/styles/theme.scss';
+import less from 'less'
+Vue.use(less)
 
 import Element from 'element-ui'
 import './assets/styles/element-variables.scss'

+ 81 - 0
ruoyi-ui/src/utils/dateApi.js

@@ -0,0 +1,81 @@
+
+/**
+ * 返回yyyy-MM-dd hh:mm:ss 或者 yyyy-MM-dd格式的日期字符串
+ * 如:"2016-09-22T08:37:43.438Z" --> "2016-09-22 08:37:43"
+ * 传参格式: yyyy-MM-dd hh:mm:ss yyyy-MM-dd
+ */
+Date.prototype.format = function(fmt) { 
+  var o = { 
+     "M+" : this.getMonth()+1,                 //月份 
+     "d+" : this.getDate(),                    //日 
+     "h+" : this.getHours(),                   //小时 
+     "m+" : this.getMinutes(),                 //分 
+     "s+" : this.getSeconds(),                 //秒 
+     "q+" : Math.floor((this.getMonth()+3)/3), //季度 
+     "S"  : this.getMilliseconds()             //毫秒 
+ }; 
+ if(/(y+)/.test(fmt)) {
+         fmt=fmt.replace(RegExp.$1, (this.getFullYear()+"").substr(4 - RegExp.$1.length)); 
+ }
+  for(var k in o) {
+     if(new RegExp("("+ k +")").test(fmt)){
+          fmt = fmt.replace(RegExp.$1, (RegExp.$1.length==1) ? (o[k]) : (("00"+ o[k]).substr((""+ o[k]).length)));
+      }
+  }
+ return fmt; 
+}  
+ 
+/**
+ * 返回一个加上days天的新Date
+ */
+Date.prototype.plusDays = function plusDays(days) {
+  return new Date(this.getTime() + days * 60 * 60 * 24 * 1000);
+};
+ 
+/**
+ * 返回一个减去days天的新Date
+ */
+Date.prototype.minusDays = function minusDays(days) {
+  return new Date(this.getTime() - days * 60 * 60 * 24 * 1000);
+};
+ 
+/**
+ * 返回一个加上若干个月的新Date
+ * 注1:Date(2-28).plusMonth(1)=Date(3-28)。如果需要变成3-31,需要另外的函数来处理。
+ * 注2:Date(1-31).plusMonth(1)=Date(2-28)或Date(2-29)
+ */
+Date.prototype.plusMonths = function plusMonths(num) {
+  const newDate = new Date(this);
+  newDate.setMonth(this.getMonth() + num); // setMonth()会自动除以12
+  // 注意:此时,月数可能会自动进位,比如:1-31加上num=1的情况,会变成3-3(非闰年)或3-2(闰年),即2-31自动转换为下个月的某一天。
+  const currentMonth = this.getMonth() + this.getFullYear() * 12; // 获得月的绝对值
+  const diff = (newDate.getMonth() + newDate.getFullYear() * 12) - currentMonth; // 计算新旧两个月绝对值的差
+
+  if (diff !== num) { // 如果月绝对值的差和加上的月数不一样,说明月进位了,此时需要退一个月
+    // setDate(0)表示变成上个月的最后一天
+    newDate.setDate(0);
+  }
+  return newDate;
+};
+ 
+/**
+ * 返回下个月的第一天的Date对象
+ */
+Date.prototype.getStartOfNextMonth = function getStartOfNextMonth() {
+  const newDate = new Date(this);
+  newDate.setDate(15); // 确保月数不会进位
+  newDate.setMonth(this.getMonth() + 1);
+  newDate.setDate(1);
+  return newDate;
+}; 
+ 
+/**
+ * 返回下个月的最后一天的Date对象
+ */
+Date.prototype.getEndOfNextMonth = function getEndOfNextMonth() {
+  const newDate = new Date(this);
+  newDate.setDate(15); // 确保月数不会进位
+  newDate.setMonth(this.getMonth() + 2); // 加两个月
+  newDate.setDate(0); // 再退回上个月的最后一天
+  return newDate;
+};

+ 26 - 23
ruoyi-ui/src/views/activiti/TemplateManagementNew/index.vue

@@ -1,12 +1,10 @@
 <template>
   <div class="TemplateManagementNew">
-    <Breadcrumb separator=">" class="breadcrumb">
+  <!--  <Breadcrumb separator=">" class="breadcrumb">
         <BreadcrumbItem to="/TemplateManagementLists">模版管理</BreadcrumbItem>
         <BreadcrumbItem>{{$route.params.id != '-1'?'编辑模版':'新建模版'}}</BreadcrumbItem>
 
-    </Breadcrumb>
-
-
+    </Breadcrumb> -->
     <!-- 预览状态 -->
     <div class="content" v-if="this.readOnly">
       <div class="tips" v-if="currentSteps === 2">
@@ -80,6 +78,12 @@ import FlowChartComponent from '@/components/FlowChartComponent'
 import FlowSuccess from '@/components/FlowSuccess'
 import {  mapMutations } from 'vuex';
 import { setTimeout } from 'timers';
+import {
+    getLoad,
+    getCommit,
+    getDuplicate,
+    getPublish
+  } from '@/api/modeler.js'
 export default {
   name:'TemplateManagementNew',
   components:{ParameterConfiguration,FlowChartComponent,FlowSuccess},
@@ -197,22 +201,22 @@ export default {
   methods:{
     ...mapMutations(['currentChange']),
     getModuleInfo (id) {
-      this.$network.post('/p/cs/module/load', {id:id}).then((res) => {
-        if(res.data.resultCode === 0){
-          res.data.data.businessType = [{
-            ID:res.data.data.businessType,
-            Label:res.data.data.businessTypeName,
-            val:res.data.data.businessTypeText
+      getLoad({id:id}).then((res) => {
+        if(res.resultCode === 0){
+          res.data.businessType = [{
+            ID:res.data.businessType,
+            Label:res.data.businessTypeName,
+            val:res.data.businessTypeText
           }]
 
-          res.data.data.businessNumber = [{
-            ID:String(res.data.data.businessKeyId),
-            Label:res.data.data.businessKey,
-            val:res.data.data.businessKeyName
+          res.data.businessNumber = [{
+            ID:String(res.data.businessKeyId),
+            Label:res.data.businessKey,
+            val:res.data.businessKeyName
           }]
-          this.data = res.data.data
-          this.data.guiStyle = JSON.parse(res.data.data.guiStyle)
-          this.data.moduleId = res.data.data.id
+          this.data = res.data
+          this.data.guiStyle = JSON.parse(res.data.guiStyle)
+          this.data.moduleId = res.data.id
 
           this.$nextTick(() => {
             if(this.readOnly){
@@ -279,16 +283,15 @@ export default {
           ID:this.data.moduleId,
           NAME:this.data.name
         }
-        this.$network.post('/p/cs/module/duplicate',jsonObject).then(res => {
-            if(res.data.resultCode !== 0){
+        getDuplicate(jsonObject).then(res => {
+            if(res.resultCode !== 0){
               this.$Modal.fcWarning({
                 title:'警告',
-                content:res.data.resultMsg,
+                content:res.resultMsg,
                 mask:true
               })
               reject()
             }
-
             resolve(res)
         })
       })
@@ -336,7 +339,7 @@ export default {
           removeNode: this.data.removeNode,
           removePath: this.data.removePath
         }
-        this.$network.post('/p/cs/module/commit',jsonObject).then(res => {
+        getCommit(jsonObject).then(res => {
             if(res.data.resultCode === 0){
               // this.data = {
               //   guiStyle:{
@@ -459,7 +462,7 @@ export default {
     },
     confirmAndPublish () {  //保存并发布
       this.confirm(true).then(res => {
-        this.$network.post('/p/cs/module/publish', {id:res.data.data.id}).then((response) => {
+        getPublish({id:res.data.data.id}).then((response) => {
           if(response.data.resultCode === 0){
             this.$router.push('/TemplateManagementLists')
             this.currentChange({

+ 18 - 13
ruoyi-ui/src/views/activiti/modeler/index.vue

@@ -6,19 +6,19 @@
           <el-button type="primary" plain size="mini" @click="searchData.page = 1;queryLists()">查询</el-button>
         </el-col>
         <el-col :span="1.5">
-          <el-button type="warning" plain :disabled="listsStatus === 1" size="mini" @click="addTemplate" v-hasPermi="['tool:gen:code']">新建模板</el-button>
+          <el-button type="warning" plain :disabled="listsStatus === 1" size="mini" @click="addTemplate">新建模板</el-button>
         </el-col>
         <el-col :span="1.5">
-          <el-button type="primary" plain :disabled="listsStatus === 1" size="mini" @click="templateMigration" v-if="listsStatus === 0" v-hasPermi="['tool:gen:code']">模版迁移</el-button>
+          <el-button type="primary" plain size="mini" @click="templateMigration" v-if="listsStatus === 0">模版迁移</el-button>
         </el-col>
         <el-col :span="1.5">
-          <el-button type="primary" plain :disabled="listsStatus === 1" size="mini" @click="removeMigration" v-if="listsStatus === 1" v-hasPermi="['tool:gen:code']">取消迁移</el-button>
+          <el-button type="primary" plain size="mini" @click="removeMigration" v-if="listsStatus === 1">取消迁移</el-button>
         </el-col>
         <el-col :span="1.5">
-          <el-button type="primary" plain :disabled="listsStatus === 1" size="mini" @click="perform" v-if="listsStatus === 1" v-hasPermi="['tool:gen:code']">执行</el-button>
+          <el-button type="primary" plain size="mini" @click="perform" v-if="listsStatus === 1">执行</el-button>
         </el-col>
         <el-col :span="1.5">
-          <el-button type="primary" plain :disabled="listsStatus === 1" size="mini" @click="performAll" v-if="listsStatus === 1" v-hasPermi="['tool:gen:code']">执行全部</el-button>
+          <el-button type="primary" plain size="mini" @click="performAll" v-if="listsStatus === 1">执行全部</el-button>
         </el-col>
         </el-row>
       <Alert show-icon closable v-if="listsStatus === 1">依次单击模板可进行多选模板</Alert>
@@ -83,7 +83,8 @@ import ItemComponent from '@/components/ItemComponent';
 import StandardTable from '@/components/StandardTable';
 import listModalComponent from '@/components/listModalComponent'
 import {
-    getSearch
+    getSearch,
+    setMigrate
   } from '@/api/modeler.js'
 
 // import router from '../config/router.config'
@@ -257,7 +258,7 @@ export default {
     },
     addTemplate () {  //新建模版
       this.changeKeepAliveArray(['TemplateManagementLists'])
-      this.$router.push({ path: '/TemplateManagementNew/-1' })
+      this.$router.push({ path: '/tool/activiti/TemplateManagementNew/-1' })
       this.currentChange({
         path:'/TemplateManagementLists'
       });
@@ -324,12 +325,11 @@ export default {
       }
 
       obj.url = this.serverUrl
-      this.$network.post('/p/cs/module/migrate', obj)
-        .then((res) => {
-          if(res.data.resultCode === 0){
+      setMigrate(obj).then((res) => {
+          if(res.resultCode === 0){
             this.$Modal.fcSuccess({
               title:'成功',
-              content:res.data.resultMsg,
+              content:res.resultMsg,
               onOk: () => {
                 this.queryLists()
                 this.listsStatus = 0
@@ -339,9 +339,14 @@ export default {
             })
 
           }else{
-            this.performloading = false
+            this.$Modal.fcError({
+              title:'错误',
+              content:res.resultMsg,
+              onOk: () => {
+                this.performloading = false
+              }
+            })
           }
-
         })
     }
   },

+ 57 - 13
ruoyi-ui/src/views/system/role/fz-index.vue

@@ -17,7 +17,7 @@
           </el-col>
           <el-col :span="1.5">
             <el-button type="primary" style="background-color: #3C8DBC;color: #fff;border: none;" plain icon="el-icon-my-export"
-              @click="handleAdd" v-hasPermi="['system:role:edit']">保存</el-button>
+              @click="handleMenu" v-hasPermi="['system:role:edit']">保存</el-button>
           </el-col>
         </el-row>
       </el-col>
@@ -57,7 +57,7 @@
                   功能
                 </div>
                 <div class="searItem" v-for="item in menusList.heads">
-                  <el-checkbox :label="item.name"></el-checkbox>
+                  {{item.name}}
                 </div>
               </div>
               <div class="searCont" v-if="menusList.sysMenus.length" v-for="items in menusList.sysMenus" @click="searIndex = items.id" :class="{'active': searIndex == items.id}" :key="items.id">
@@ -65,10 +65,7 @@
                   {{items.menuName}}
                 </div>
                 <div class="searItem" v-for="(itemChild,indexChild) in items.containsHead" :key="indexChild">
-                  <!-- <el-checkbox-group v-model="checkedCities">
-                      <el-checkbox v-for="(item,index) in items.containsHead" :key="index"></el-checkbox>
-                  </el-checkbox-group> -->
-                  <el-checkbox></el-checkbox>
+                  <el-checkbox @change="checkChange" :disabled="itemChild.type==='0'" v-model="itemChild.type"></el-checkbox>
                 </div>
               </div>
             </div>
@@ -111,6 +108,7 @@
     updateRole,
     exportRole,
     dataScope,
+    setMenu,
     changeRoleStatus
   } from "@/api/system/role";
   import {
@@ -124,9 +122,11 @@
   } from "@/api/system/dept";
 
   export default {
-    name: "Role",
+    name: "Role",
+    inject: ['reload'],
     data() {
       return {
+        modifyStatus: false,
         fullscreenLoading: false,
         searIndex: '',
         data: [],
@@ -228,7 +228,48 @@
       });
     },
     methods: {
+      checkChange() {
+        this.modifyStatus = true
+      },
+      handleMenu() {
+        if(!this.modifyStatus){
+          this.msgInfo('没有修改的内容!')
+          return
+        }
+        let data = []
+        for(let item of this.menusList.sysMenus){
+          let obj = {}
+          obj.roleId = this.roleId
+          obj.menuId = item.id
+          obj.head = []
+          for(let itemChild of item.containsHead){
+            if(itemChild.type === true){
+              obj.head.push(itemChild.name)
+            }
+          }
+          data.push(obj)
+        }
+        setMenu(JSON.stringify(data)).then(res => {
+          this.msgSuccess('保存成功')
+          this.modifyStatus = false
+        })
+      },
       qxList(e) {
+        const _this = this
+        console.log(this.modifyStatus)
+        if(this.modifyStatus){
+          this.$confirm('当前页面存在未保存内容,是否保存后切换?', "提醒", {
+            confirmButtonText: "留下",
+            cancelButtonText: "取消",
+            type: "warning"
+          }).then(function() {
+
+          }).catch(function() {
+            _this.modifyStatus = false
+            _this.qxList(e)
+          });
+          return
+        }
         listMenus(e.id).then(res => {
           let data = res.data
           this.menusList = data
@@ -475,7 +516,7 @@
           confirmButtonText: "确定",
           cancelButtonText: "取消",
           type: "warning",
-          
+
         }).then(function() {
           return delRole(ids);
         }).then(() => {
@@ -533,12 +574,13 @@
         .searName {
           color: #343434;
           font-size: 12px;
-          width: 156px;
+          width: 116px;
         }
 
         .searItem {
           flex: 1;
-          font-size: 12px;
+          font-size: 12px;
+          text-align: center;
         }
       }
 
@@ -553,12 +595,13 @@
         .searName {
           color: #343434;
           font-size: 12px;
-          width: 156px;
+          width: 116px;
         }
 
         .searItem {
           flex: 1;
-          font-size: 12px;
+          font-size: 12px;
+          text-align: center;
         }
 
         &:hover {
@@ -630,7 +673,8 @@
         line-height: 30px;
         font-size: 12px;
         color: #343434;
-        cursor: pointer;
+        cursor: pointer;
+        text-align: center;
       }
 
       .active {