Browse Source

flowable-1

csg6 1 week ago
parent
commit
f20ac91822

+ 3 - 3
.env.development

@@ -5,9 +5,9 @@ VUE_APP_TITLE = 双重预防综合管理系统
5
 ENV = 'development'
5
 ENV = 'development'
6
 
6
 
7
 # 双重防御系统开发环境后台接口地址配置
7
 # 双重防御系统开发环境后台接口地址配置
8
-VUE_APP_BASE_API = 'http://101.42.248.108:17007'
9
-# VUE_APP_BASE_API = 'http://192.168.29.184:18080'
10
-#VUE_APP_BASE_API = 'http://localhost:18080'
8
+# VUE_APP_BASE_API = 'http://101.42.248.108:17005'
9
+VUE_APP_BASE_API = 'http://192.168.3.200:18080'
10
+# VUE_APP_BASE_API = 'http://localhost:18080'
11
 
11
 
12
 
12
 
13
 # 路由懒加载
13
 # 路由懒加载

File diff suppressed because it is too large
+ 0 - 14818
package-lock.json


+ 13 - 8
package.json

@@ -38,28 +38,31 @@
38
   "dependencies": {
38
   "dependencies": {
39
     "@jiaminghi/data-view": "^2.10.0",
39
     "@jiaminghi/data-view": "^2.10.0",
40
     "@riophae/vue-treeselect": "0.4.0",
40
     "@riophae/vue-treeselect": "0.4.0",
41
-    "FileSaver": "^0.10.0",
42
     "amfe-flexible": "^2.2.1",
41
     "amfe-flexible": "^2.2.1",
43
     "animate.css": "^4.1.1",
42
     "animate.css": "^4.1.1",
44
-    "axios": "0.24.0",
43
+    "axios": "^1.7.7",
44
+    "bpmn-js": "^11.1.0",
45
     "clipboard": "2.0.8",
45
     "clipboard": "2.0.8",
46
     "core-js": "^3.32.0",
46
     "core-js": "^3.32.0",
47
+    "diagram-js": "^11.4.1",
47
     "docx-preview": "^0.1.18",
48
     "docx-preview": "^0.1.18",
48
     "echarts": "5.4.0",
49
     "echarts": "5.4.0",
49
     "element-ui": "2.15.13",
50
     "element-ui": "2.15.13",
50
     "express": "^4.18.2",
51
     "express": "^4.18.2",
51
     "file-saver": "2.0.5",
52
     "file-saver": "2.0.5",
53
+    "FileSaver": "^0.10.0",
52
     "fuse.js": "6.4.3",
54
     "fuse.js": "6.4.3",
53
-    "highlight.js": "9.18.5",
55
+    "highlight.js": "^9.18.5",
54
     "js-beautify": "1.13.0",
56
     "js-beautify": "1.13.0",
55
     "js-cookie": "3.0.1",
57
     "js-cookie": "3.0.1",
56
     "jsencrypt": "3.0.0-rc.1",
58
     "jsencrypt": "3.0.0-rc.1",
57
     "moment": "^2.29.4",
59
     "moment": "^2.29.4",
58
     "nodemon": "^3.0.1",
60
     "nodemon": "^3.0.1",
59
     "nprogress": "0.2.0",
61
     "nprogress": "0.2.0",
60
-    "quill": "1.3.7",
62
+    "quill": "^1.3.7",
61
     "screenfull": "5.0.2",
63
     "screenfull": "5.0.2",
62
     "sortablejs": "1.10.2",
64
     "sortablejs": "1.10.2",
65
+    "vkbeautify": "^0.99.3",
63
     "vue": "2.6.12",
66
     "vue": "2.6.12",
64
     "vue-count-to": "1.0.13",
67
     "vue-count-to": "1.0.13",
65
     "vue-cropper": "0.5.5",
68
     "vue-cropper": "0.5.5",
@@ -70,26 +73,28 @@
70
     "vue2-org-tree": "^1.3.6",
73
     "vue2-org-tree": "^1.3.6",
71
     "vuedraggable": "2.24.3",
74
     "vuedraggable": "2.24.3",
72
     "vuex": "3.6.0",
75
     "vuex": "3.6.0",
76
+    "xcrud": "^0.4.19",
73
     "xlsx": "^0.18.5"
77
     "xlsx": "^0.18.5"
74
   },
78
   },
75
   "devDependencies": {
79
   "devDependencies": {
76
-    "@vue/cli-plugin-babel": "4.4.6",
77
-    "@vue/cli-plugin-eslint": "4.4.6",
80
+    "@vue/cli-plugin-babel": "^5.0.8",
81
+    "@vue/cli-plugin-eslint": "^5.0.8",
78
     "@vue/cli-service": "4.4.6",
82
     "@vue/cli-service": "4.4.6",
79
     "babel-eslint": "10.1.0",
83
     "babel-eslint": "10.1.0",
80
     "babel-plugin-dynamic-import-node": "2.3.3",
84
     "babel-plugin-dynamic-import-node": "2.3.3",
81
     "chalk": "4.1.0",
85
     "chalk": "4.1.0",
82
     "compression-webpack-plugin": "5.0.2",
86
     "compression-webpack-plugin": "5.0.2",
83
     "connect": "3.6.6",
87
     "connect": "3.6.6",
88
+    "create-bpmnlint-plugin": "^0.6.0",
84
     "eslint": "7.15.0",
89
     "eslint": "7.15.0",
85
     "eslint-plugin-vue": "7.2.0",
90
     "eslint-plugin-vue": "7.2.0",
86
     "lint-staged": "10.5.3",
91
     "lint-staged": "10.5.3",
87
     "postcss-pxtorem": "^5.1.1",
92
     "postcss-pxtorem": "^5.1.1",
88
-    "runjs": "4.4.2",
93
+    "runjs": "^4.1.3",
89
     "sass": "1.32.13",
94
     "sass": "1.32.13",
90
     "sass-loader": "10.1.1",
95
     "sass-loader": "10.1.1",
91
     "script-ext-html-webpack-plugin": "2.1.5",
96
     "script-ext-html-webpack-plugin": "2.1.5",
92
-    "svg-sprite-loader": "5.1.1",
97
+    "svg-sprite-loader": "^5.2.1",
93
     "vue-template-compiler": "2.6.12"
98
     "vue-template-compiler": "2.6.12"
94
   },
99
   },
95
   "engines": {
100
   "engines": {

+ 191 - 0
src/components/flow/ElInputTag/index.vue

@@ -0,0 +1,191 @@
1
+<template>
2
+  <div
3
+      class="el-input-tag input-tag-wrapper"
4
+      :class="[size ? 'el-input-tag--' + size : '']"
5
+      @click="focusTagInput">
6
+    <el-tag
7
+        v-for="(tag, idx) in innerTags"
8
+        v-bind="$attrs"
9
+        :key="tag"
10
+        :size="size"
11
+        effect="dark"
12
+        closable
13
+        :disable-transitions="false"
14
+        @close="remove(idx)">
15
+      {{tag}}
16
+    </el-tag>
17
+    <input
18
+        v-if="!readOnly"
19
+        class="tag-input"
20
+        :placeholder="placeholder"
21
+        @input="inputTag"
22
+        :value="newTag"
23
+        @keydown.delete.stop = "removeLastTag"
24
+    />
25
+<!--    @keydown = "addNew"
26
+        @blur = "addNew"-->
27
+  </div>
28
+</template>
29
+
30
+
31
+<script>
32
+import {StrUtil} from '@/utils/StrUtil'
33
+
34
+export default {
35
+  name: "ElInputTag",
36
+  /** 组件传值  */
37
+  props : {
38
+    value: {
39
+      type: String,
40
+      default: ""
41
+    },
42
+    addTagOnKeys: {
43
+      type: Array,
44
+      default: () => []
45
+    },
46
+    size: {
47
+      type: String,
48
+      default: 'small'
49
+    },
50
+    placeholder: String,
51
+  },
52
+  data() {
53
+    return {
54
+       newTag :"",
55
+       innerTags :[],
56
+       readOnly :true,
57
+    }
58
+  },
59
+  /** 传值监听 */
60
+  watch: {
61
+    value: {
62
+      handler(newVal) {
63
+        if (StrUtil.isNotBlank(newVal)) {
64
+          this.innerTags = newVal.split(',');
65
+        }else {
66
+          this.innerTags = [];
67
+        }
68
+      },
69
+      immediate: true, // 立即生效
70
+    },
71
+  },
72
+  methods: {
73
+    focusTagInput() {
74
+      if (this.readOnly || !this.$el.querySelector('.tag-input')) {
75
+        return
76
+      } else {
77
+        this.$el.querySelector('.tag-input').focus()
78
+      }
79
+    },
80
+
81
+    inputTag(ev) {
82
+     this.newTag = ev.target.value
83
+    },
84
+
85
+    addNew(e) {
86
+      if (e && (!this.addTagOnKeys.includes(e.keyCode)) && (e.type !== 'blur')) {
87
+        return
88
+      }
89
+      if (e) {
90
+        e.stopPropagation()
91
+        e.preventDefault()
92
+      }
93
+      let addSuccess = false
94
+      if (this.newTag.includes(',')) {
95
+       this.newTag.split(',').forEach(item => {
96
+          if (this.addTag(item.trim())) {
97
+            addSuccess = true
98
+          }
99
+        })
100
+      } else {
101
+        if (this.addTag(this.newTag.trim())) {
102
+          addSuccess = true
103
+        }
104
+      }
105
+      if (addSuccess) {
106
+        this.tagChange()
107
+       this.newTag = ''
108
+      }
109
+    },
110
+
111
+    addTag(tag) {
112
+      tag = tag.trim()
113
+      if (tag && !this.innerTags.includes(tag)) {
114
+        this.innerTags.push(tag)
115
+        return true
116
+      }
117
+      return false
118
+    },
119
+
120
+    remove(index) {
121
+      this.innerTags.splice(index, 1)
122
+      this.tagChange();
123
+    },
124
+
125
+    removeLastTag() {
126
+      if (this.newTag) {
127
+        return
128
+      }
129
+      this.innerTags.pop()
130
+      this.tagChange()
131
+    },
132
+
133
+    tagChange() {
134
+      this.$emit('input', this.innerTags)
135
+    }
136
+  }
137
+}
138
+
139
+</script>
140
+
141
+<style scoped>
142
+.el-form-item.is-error .el-input-tag {
143
+  border-color: #f56c6c;
144
+}
145
+.input-tag-wrapper {
146
+  position: relative;
147
+  font-size: 14px;
148
+  background-color: #fff;
149
+  background-image: none;
150
+  border-radius: 4px;
151
+  border: 1px solid #dcdfe6;
152
+  box-sizing: border-box;
153
+  color: #606266;
154
+  display: inline-block;
155
+  outline: none;
156
+  padding: 0 10px 0 5px;
157
+  transition: border-color .2s cubic-bezier(.645,.045,.355,1);
158
+  width: 100%;
159
+}
160
+.el-tag {
161
+  margin-right: 4px;
162
+}
163
+
164
+.tag-input {
165
+  background: transparent;
166
+  border: 0;
167
+  font-size: inherit;
168
+  outline: none;
169
+  padding-left: 0;
170
+  width: 100px;
171
+}
172
+.el-input-tag {
173
+  min-height: 42px;
174
+}
175
+.el-input-tag--small {
176
+  min-height: 32px;
177
+  line-height: 32px;
178
+  font-size: 12px;
179
+}
180
+
181
+.el-input-tag--default {
182
+  min-height: 34px;
183
+  line-height: 34px;
184
+}
185
+
186
+.el-input-tag--large {
187
+  min-height: 36px;
188
+  line-height: 36px;
189
+}
190
+
191
+</style>

+ 133 - 0
src/components/flow/Expression/index.vue

@@ -0,0 +1,133 @@
1
+<template>
2
+  <div class="app-container">
3
+    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
4
+      <el-form-item label="名称" prop="name">
5
+        <el-input
6
+          v-model="queryParams.name"
7
+          placeholder="请输入表达式名称"
8
+          clearable
9
+          @keyup.enter.native="handleQuery"
10
+        />
11
+      </el-form-item>
12
+      <el-form-item>
13
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
14
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
15
+      </el-form-item>
16
+    </el-form>
17
+
18
+    <el-table v-loading="loading" :data="expressionList" @current-change="handleSingleExpSelect">
19
+      <el-table-column  width="55" align="center" >
20
+        <template slot-scope="scope">
21
+          <!-- 可以手动的修改label的值,从而控制选择哪一项 -->
22
+          <el-radio v-model="radioSelected" :label="scope.row.id">{{''}}</el-radio>
23
+        </template>
24
+      </el-table-column>
25
+      <el-table-column label="名称" align="center" prop="name" />
26
+      <el-table-column label="表达式内容" align="center" prop="expression" />
27
+      <el-table-column label="表达式类型" align="center" prop="dataType" >
28
+        <template slot-scope="scope">
29
+          <dict-tag :options="dict.type.exp_data_type" :value="scope.row.dataType"/>
30
+        </template>
31
+      </el-table-column>
32
+    </el-table>
33
+
34
+    <pagination
35
+      v-show="total>0"
36
+      :total="total"
37
+      :page-sizes="[5,10]"
38
+      layout="prev, pager, next"
39
+      :page.sync="queryParams.pageNum"
40
+      :limit.sync="queryParams.pageSize"
41
+      @pagination="getList"
42
+    />
43
+  </div>
44
+</template>
45
+
46
+<script>
47
+import { listExpression } from "@/api/flowable/expression";
48
+import {StrUtil} from "@/utils/StrUtil";
49
+
50
+export default {
51
+  name: "Expression",
52
+  dicts: ['sys_common_status','exp_data_type'],
53
+  // 接受父组件的值
54
+  props: {
55
+    // 回显数据传值
56
+    selectValues: {
57
+      type: Number | String,
58
+      default: null,
59
+      required: false
60
+    }
61
+  },
62
+  data() {
63
+    return {
64
+      // 遮罩层
65
+      loading: true,
66
+      // 选中数组
67
+      ids: [],
68
+      // 非单个禁用
69
+      single: true,
70
+      // 非多个禁用
71
+      multiple: true,
72
+      // 显示搜索条件
73
+      showSearch: true,
74
+      // 总条数
75
+      total: 0,
76
+      // 流程达式表格数据
77
+      expressionList: [],
78
+      // 弹出层标题
79
+      title: "",
80
+      // 是否显示弹出层
81
+      open: false,
82
+      // 查询参数
83
+      queryParams: {
84
+        pageNum: 1,
85
+        pageSize: 10,
86
+        name: null,
87
+        expression: null,
88
+        status: null,
89
+      },
90
+      radioSelected: null // 单选框传值
91
+    };
92
+  },
93
+  watch: {
94
+    selectValues: {
95
+      handler(newVal) {
96
+        if (StrUtil.isNotBlank(newVal)) {
97
+          this.radioSelected = newVal
98
+        }
99
+      },
100
+      immediate: true,
101
+    }
102
+  },
103
+  created() {
104
+    this.getList();
105
+  },
106
+  methods: {
107
+    /** 查询流程达式列表 */
108
+    getList() {
109
+      this.loading = true;
110
+      listExpression(this.queryParams).then(response => {
111
+        this.expressionList = response.rows;
112
+        this.total = response.total;
113
+        this.loading = false;
114
+      });
115
+    },
116
+    /** 搜索按钮操作 */
117
+    handleQuery() {
118
+      this.queryParams.pageNum = 1;
119
+      this.getList();
120
+    },
121
+    /** 重置按钮操作 */
122
+    resetQuery() {
123
+      this.resetForm("queryForm");
124
+      this.handleQuery();
125
+    },
126
+    // 单选框选中数据
127
+    handleSingleExpSelect(selection) {
128
+      this.radioSelected = selection.id;//点击当前行时,radio同样有选中效果
129
+      this.$emit('handleSingleExpSelect',selection);
130
+    },
131
+  }
132
+};
133
+</script>

+ 187 - 0
src/components/flow/Role/index.vue

@@ -0,0 +1,187 @@
1
+<template>
2
+  <div class="app-container">
3
+    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch">
4
+      <el-form-item label="角色名称" prop="roleName">
5
+        <el-input
6
+          v-model="queryParams.roleName"
7
+          placeholder="请输入角色名称"
8
+          clearable
9
+          style="width: 240px"
10
+          @keyup.enter.native="handleQuery"
11
+        />
12
+      </el-form-item>
13
+      <el-form-item>
14
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
15
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
16
+      </el-form-item>
17
+    </el-form>
18
+
19
+    <el-table v-show="checkType === 'multiple'" ref="dataTable"  v-loading="loading" :data="roleList" @selection-change="handleMultipleRoleSelect">
20
+      <el-table-column type="selection" width="50" align="center" />
21
+      <el-table-column label="角色编号" prop="roleId" width="120" />
22
+      <el-table-column label="角色名称" prop="roleName" :show-overflow-tooltip="true" width="150" />
23
+      <el-table-column label="权限字符" prop="roleKey" :show-overflow-tooltip="true" width="150" />
24
+      <el-table-column label="显示顺序" prop="roleSort" width="100" />
25
+      <el-table-column label="创建时间" align="center" prop="createTime" width="180">
26
+        <template slot-scope="scope">
27
+          <span>{{ parseTime(scope.row.createTime) }}</span>
28
+        </template>
29
+      </el-table-column>
30
+    </el-table>
31
+    <el-table v-show="checkType === 'single'" v-loading="loading" :data="roleList" @current-change="handleSingleRoleSelect">
32
+      <el-table-column  width="55" align="center" >
33
+        <template slot-scope="scope">
34
+          <!-- 可以手动的修改label的值,从而控制选择哪一项 -->
35
+          <el-radio v-model="radioSelected" :label="scope.row.roleId">{{''}}</el-radio>
36
+        </template>
37
+      </el-table-column>
38
+      <el-table-column label="角色编号" prop="roleId" width="120" />
39
+      <el-table-column label="角色名称" prop="roleName" :show-overflow-tooltip="true" width="150" />
40
+      <el-table-column label="权限字符" prop="roleKey" :show-overflow-tooltip="true" width="150" />
41
+      <el-table-column label="显示顺序" prop="roleSort" width="100" />
42
+      <el-table-column label="创建时间" align="center" prop="createTime" width="180">
43
+        <template slot-scope="scope">
44
+          <span>{{ parseTime(scope.row.createTime) }}</span>
45
+        </template>
46
+      </el-table-column>
47
+    </el-table>
48
+
49
+    <pagination
50
+      v-show="total>0"
51
+      :total="total"
52
+      :page-sizes="[5,10]"
53
+      layout="prev, pager, next"
54
+      :page.sync="queryParams.pageNum"
55
+      :limit.sync="queryParams.pageSize"
56
+      @pagination="getList"
57
+    />
58
+  </div>
59
+</template>
60
+
61
+<script>
62
+import { listRole} from "@/api/system/role";
63
+import {StrUtil} from "@/utils/StrUtil";
64
+
65
+export default {
66
+  name: "FlowRole",
67
+  dicts: ['sys_normal_disable'],
68
+  // 接受父组件的值
69
+  props: {
70
+    // 回显数据传值
71
+    selectValues: {
72
+      type: Number | String | Array,
73
+      default: null,
74
+      required: false
75
+    },
76
+    checkType: {
77
+      type: String,
78
+      default: 'multiple',
79
+      required: false
80
+    },
81
+  },
82
+  data() {
83
+    return {
84
+      // 遮罩层
85
+      loading: true,
86
+      // 选中数组
87
+      ids: [],
88
+      // 非单个禁用
89
+      single: true,
90
+      // 非多个禁用
91
+      multiple: true,
92
+      // 显示搜索条件
93
+      showSearch: true,
94
+      // 总条数
95
+      total: 0,
96
+      // 角色表格数据
97
+      roleList: [],
98
+      // 弹出层标题
99
+      title: "",
100
+      // 是否显示弹出层
101
+      open: false,
102
+      // 查询参数
103
+      queryParams: {
104
+        pageNum: 1,
105
+        pageSize: 5,
106
+        roleName: undefined,
107
+        roleKey: undefined,
108
+        status: undefined
109
+      },
110
+      // 表单参数
111
+      form: {},
112
+      radioSelected: 0, // 单选框传值
113
+      selectRoleList: [] // 回显数据传值
114
+    };
115
+  },
116
+  watch: {
117
+    selectValues: {
118
+      handler(newVal) {
119
+        if (StrUtil.isNotBlank(newVal)) {
120
+          if (newVal instanceof Number || newVal instanceof String) {
121
+            this.radioSelected = newVal
122
+          } else {
123
+            this.selectRoleList = newVal;
124
+          }
125
+        }
126
+      },
127
+      immediate: true
128
+    },
129
+    roleList: {
130
+      handler(newVal) {
131
+        if (StrUtil.isNotBlank(newVal) && this.selectRoleList.length > 0) {
132
+          this.$nextTick(() => {
133
+            this.$refs.dataTable.clearSelection();
134
+            this.selectRoleList?.split(',').forEach(key => {
135
+              this.$refs.dataTable.toggleRowSelection(newVal.find(
136
+                item => key == item.roleId
137
+              ), true)
138
+            });
139
+          });
140
+        }
141
+      }
142
+    }
143
+  },
144
+  created() {
145
+    this.getList();
146
+  },
147
+  methods: {
148
+    /** 查询角色列表 */
149
+    getList() {
150
+      this.loading = true;
151
+      listRole(this.queryParams).then(response => {
152
+          this.roleList = response.rows;
153
+          this.total = response.total;
154
+          this.loading = false;
155
+        }
156
+      );
157
+    },
158
+    // 多选框选中数据
159
+    handleMultipleRoleSelect(selection) {
160
+      const idList = selection.map(item => item.roleId);
161
+      const nameList = selection.map(item => item.roleName);
162
+      this.$emit('handleRoleSelect', idList.join(','), nameList.join(','));
163
+    },
164
+    // 单选框选中数据
165
+    handleSingleRoleSelect(selection) {
166
+      this.radioSelected = selection.roleId;
167
+      const roleName = selection.roleName;
168
+      this.$emit('handleRoleSelect', this.radioSelected.toString(), roleName);
169
+    },
170
+    /** 搜索按钮操作 */
171
+    handleQuery() {
172
+      this.queryParams.pageNum = 1;
173
+      this.getList();
174
+    },
175
+    /** 重置按钮操作 */
176
+    resetQuery() {
177
+      this.handleQuery();
178
+    },
179
+  }
180
+};
181
+</script>
182
+<style>
183
+/*隐藏radio展示的label及本身自带的样式*/
184
+/*.el-radio__label{*/
185
+/*  display:none;*/
186
+/*}*/
187
+</style>

+ 257 - 0
src/components/flow/User/index.vue

@@ -0,0 +1,257 @@
1
+<template>
2
+  <div>
3
+    <el-row :gutter="20">
4
+      <!--部门数据-->
5
+      <el-col :span="6" :xs="24">
6
+        <div class="head-container">
7
+          <el-input
8
+            v-model="deptName"
9
+            placeholder="请输入部门名称"
10
+            clearable
11
+            size="small"
12
+            prefix-icon="el-icon-search"
13
+            style="margin-bottom: 20px"
14
+          />
15
+        </div>
16
+        <div class="head-container">
17
+          <el-tree
18
+            :data="deptOptions"
19
+            :props="defaultProps"
20
+            :expand-on-click-node="false"
21
+            :filter-node-method="filterNode"
22
+            ref="tree"
23
+            node-key="id"
24
+            default-expand-all
25
+            highlight-current
26
+            @node-click="handleNodeClick"
27
+          />
28
+        </div>
29
+      </el-col>
30
+      <!--用户数据-->
31
+      <el-col :span="18" :xs="24">
32
+        <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
33
+          <el-form-item label="用户名称" prop="userName">
34
+            <el-input
35
+              v-model="queryParams.userName"
36
+              placeholder="请输入用户名称"
37
+              clearable
38
+              style="width: 150px"
39
+              @keyup.enter.native="handleQuery"
40
+            />
41
+          </el-form-item>
42
+          <el-form-item>
43
+            <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
44
+            <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
45
+          </el-form-item>
46
+        </el-form>
47
+        <el-table v-show="checkType === 'multiple'" ref="dataTable" v-loading="loading" :row-key="getRowKey" :data="userList" @selection-change="handleMultipleUserSelect">
48
+          <el-table-column type="selection" :reserve-selection="true" width="50" align="center" />
49
+          <el-table-column label="用户编号" align="center" key="userId" prop="userId" v-if="columns[0].visible" />
50
+          <el-table-column label="登录账号" align="center" key="userName" prop="userName" v-if="columns[1].visible" :show-overflow-tooltip="true" />
51
+          <el-table-column label="用户姓名" align="center" key="nickName" prop="nickName" v-if="columns[2].visible" :show-overflow-tooltip="true" />
52
+          <el-table-column label="部门" align="center" key="deptName" prop="dept.deptName" v-if="columns[3].visible" :show-overflow-tooltip="true" />
53
+          <el-table-column label="手机号码" align="center" key="phonenumber" prop="phonenumber" v-if="columns[4].visible" width="120" />
54
+        </el-table>
55
+        <el-table v-show="checkType === 'single'" v-loading="loading" :data="userList" @current-change="handleSingleUserSelect">
56
+          <el-table-column  width="55" align="center" >
57
+            <template slot-scope="scope">
58
+              <el-radio v-model="radioSelected" :label="scope.row.userId">{{''}}</el-radio>
59
+            </template>
60
+          </el-table-column>
61
+          <el-table-column label="用户编号" align="center" key="userId" prop="userId" v-if="columns[0].visible" />
62
+          <el-table-column label="登录账号" align="center" key="userName" prop="userName" v-if="columns[1].visible" :show-overflow-tooltip="true" />
63
+          <el-table-column label="用户姓名" align="center" key="nickName" prop="nickName" v-if="columns[2].visible" :show-overflow-tooltip="true" />
64
+          <el-table-column label="部门" align="center" key="deptName" prop="dept.deptName" v-if="columns[3].visible" :show-overflow-tooltip="true" />
65
+          <el-table-column label="手机号码" align="center" key="phonenumber" prop="phonenumber" v-if="columns[4].visible" width="120" />
66
+        </el-table>
67
+        <pagination
68
+          v-show="total>0"
69
+          :total="total"
70
+          :page-sizes="[5,10]"
71
+          layout="prev, pager, next"
72
+          :page.sync="queryParams.pageNum"
73
+          :limit.sync="queryParams.pageSize"
74
+          @pagination="getList"
75
+        />
76
+      </el-col>
77
+    </el-row>
78
+  </div>
79
+</template>
80
+
81
+<script>
82
+import { listUser, deptTreeSelect } from "@/api/system/user";
83
+import Treeselect from "@riophae/vue-treeselect";
84
+import "@riophae/vue-treeselect/dist/vue-treeselect.css";
85
+import {StrUtil} from '@/utils/StrUtil'
86
+
87
+export default {
88
+  name: "FlowUser",
89
+  dicts: ['sys_normal_disable', 'sys_user_sex'],
90
+  components: { Treeselect },
91
+  // 接受父组件的值
92
+  props: {
93
+    // 回显数据传值
94
+    selectValues: {
95
+      type: Number | String | Array,
96
+      default: null,
97
+      required: false
98
+    },
99
+    // 表格类型
100
+    checkType: {
101
+      type: String,
102
+      default: 'multiple',
103
+      required: true
104
+    },
105
+  },
106
+  data() {
107
+    return {
108
+      // 遮罩层
109
+      loading: true,
110
+      // 选中数组
111
+      ids: [],
112
+      // 非单个禁用
113
+      single: true,
114
+      // 非多个禁用
115
+      multiple: true,
116
+      // 显示搜索条件
117
+      showSearch: true,
118
+      // 总条数
119
+      total: 0,
120
+      // 用户表格数据
121
+      userList: [],
122
+      // 弹出层标题
123
+      title: "",
124
+      // 部门树选项
125
+      deptOptions: undefined,
126
+      // 是否显示弹出层
127
+      open: false,
128
+      // 部门名称
129
+      deptName: undefined,
130
+      // 表单参数
131
+      form: {},
132
+      defaultProps: {
133
+        children: "children",
134
+        label: "label"
135
+      },
136
+      // 查询参数
137
+      queryParams: {
138
+        pageNum: 1,
139
+        pageSize: 5,
140
+        userName: undefined,
141
+        phonenumber: undefined,
142
+        status: undefined,
143
+        deptId: undefined
144
+      },
145
+      // 列信息
146
+      columns: [
147
+        { key: 0, label: `用户编号`, visible: true },
148
+        { key: 1, label: `用户名称`, visible: true },
149
+        { key: 2, label: `用户昵称`, visible: true },
150
+        { key: 3, label: `部门`, visible: true },
151
+        { key: 4, label: `手机号码`, visible: true },
152
+        { key: 5, label: `状态`, visible: true },
153
+        { key: 6, label: `创建时间`, visible: true }
154
+      ],
155
+      radioSelected: 0, // 单选框传值
156
+      selectUserList: [] // 回显数据传值
157
+    };
158
+  },
159
+  watch: {
160
+    // 根据名称筛选部门树
161
+    deptName(val) {
162
+      this.$refs.tree.filter(val);
163
+    },
164
+    selectValues: {
165
+      handler(newVal) {
166
+        if (StrUtil.isNotBlank(newVal)) {
167
+          if (newVal instanceof Number) {
168
+            this.radioSelected = newVal
169
+          } else {
170
+            this.selectUserList = newVal;
171
+          }
172
+        }
173
+      },
174
+      immediate: true
175
+    },
176
+    userList: {
177
+      handler(newVal) {
178
+        debugger
179
+        if (StrUtil.isNotBlank(newVal) && this.selectUserList.length > 0) {
180
+            this.$nextTick(() => {
181
+              this.$refs.dataTable.clearSelection();
182
+              this.selectUserList?.split(',').forEach(key => {
183
+                this.$refs.dataTable.toggleRowSelection(newVal.find(
184
+                  item => key == item.userId
185
+                ), true)
186
+              });
187
+            });
188
+        }
189
+      }
190
+    }
191
+  },
192
+  created() {
193
+    this.getList();
194
+    this.getDeptTree();
195
+  },
196
+  methods: {
197
+    /** 查询用户列表 */
198
+    getList() {
199
+      this.loading = true;
200
+      listUser(this.queryParams).then(response => {
201
+          this.userList = response.rows;
202
+          this.total = response.total;
203
+          this.loading = false;
204
+        }
205
+      );
206
+    },
207
+    /** 查询部门下拉树结构 */
208
+    getDeptTree() {
209
+      deptTreeSelect().then(response => {
210
+        this.deptOptions = response.data;
211
+      });
212
+    },
213
+    // 保存选中的数据id,row-key就是要指定一个key标识这一行的数据
214
+    getRowKey (row) {
215
+      return row.id
216
+    },
217
+    // 筛选节点
218
+    filterNode(value, data) {
219
+      if (!value) return true;
220
+      return data.label.indexOf(value) !== -1;
221
+    },
222
+    // 节点单击事件
223
+    handleNodeClick(data) {
224
+      this.queryParams.deptId = data.id;
225
+      this.handleQuery();
226
+    },
227
+    // 多选框选中数据
228
+    handleMultipleUserSelect(selection) {
229
+      this.$emit('handleUserSelect', selection);
230
+    },
231
+    // 单选框选中数据
232
+    handleSingleUserSelect(selection) {
233
+      this.radioSelected = selection.userId;//点击当前行时,radio同样有选中效果
234
+      this.$emit('handleUserSelect', selection);
235
+    },
236
+    /** 搜索按钮操作 */
237
+    handleQuery() {
238
+      this.queryParams.pageNum = 1;
239
+      this.getList();
240
+    },
241
+    /** 重置按钮操作 */
242
+    resetQuery() {
243
+      this.dateRange = [];
244
+      this.resetForm("queryForm");
245
+      this.queryParams.deptId = undefined;
246
+      this.$refs.tree.setCurrentKey(null);
247
+      this.handleQuery();
248
+    },
249
+  }
250
+};
251
+</script>
252
+<style>
253
+/*隐藏radio展示的label及本身自带的样式*/
254
+/*.el-radio__label{*/
255
+/*  display:none;*/
256
+/*}*/
257
+</style>

+ 12 - 2
src/main.js

@@ -13,7 +13,7 @@ import directive from './directive' // directive
13
 import plugins from './plugins' // plugins
13
 import plugins from './plugins' // plugins
14
 import { download } from '@/utils/request'
14
 import { download } from '@/utils/request'
15
 import dataV from '@jiaminghi/data-view'
15
 import dataV from '@jiaminghi/data-view'
16
-
16
+import  Tinymce from  '@/components/tinymce/index';
17
 Vue.use(dataV)
17
 Vue.use(dataV)
18
 import './assets/icons' // icon
18
 import './assets/icons' // icon
19
 import './permission' // permission control
19
 import './permission' // permission control
@@ -40,7 +40,14 @@ import VueMeta from 'vue-meta'
40
 import DictData from '@/components/DictData'
40
 import DictData from '@/components/DictData'
41
 import * as echarts from "echarts"
41
 import * as echarts from "echarts"
42
 import Vue2OrgTree from 'vue2-org-tree'
42
 import Vue2OrgTree from 'vue2-org-tree'
43
+
44
+import modelerStore from '@/components/Process/common/global'
45
+// vform 表单设计器
46
+import vform from '@/components/vform/VFormDesigner.umd.min.js'
47
+import '@/components/vform/VFormDesigner.css'
43
 Vue.use(Vue2OrgTree)
48
 Vue.use(Vue2OrgTree)
49
+//同时注册了v-form-designer、v-form-render等组件
50
+Vue.use(vform)
44
 Vue.prototype.$echarts = echarts
51
 Vue.prototype.$echarts = echarts
45
 // 全局方法挂载
52
 // 全局方法挂载
46
 Vue.prototype.getDicts = getDicts
53
 Vue.prototype.getDicts = getDicts
@@ -53,7 +60,9 @@ Vue.prototype.selectDictLabels = selectDictLabels
53
 Vue.prototype.download = download
60
 Vue.prototype.download = download
54
 Vue.prototype.handleTree = handleTree
61
 Vue.prototype.handleTree = handleTree
55
 
62
 
56
-// 全局组件挂载
63
+
64
+// 全局方法挂载
65
+Vue.prototype.modelerStore = modelerStore
57
 Vue.component('DictTag', DictTag)
66
 Vue.component('DictTag', DictTag)
58
 Vue.component('Pagination', Pagination)
67
 Vue.component('Pagination', Pagination)
59
 Vue.component('RightToolbar', RightToolbar)
68
 Vue.component('RightToolbar', RightToolbar)
@@ -61,6 +70,7 @@ Vue.component('Editor', Editor)
61
 Vue.component('FileUpload', FileUpload)
70
 Vue.component('FileUpload', FileUpload)
62
 Vue.component('ImageUpload', ImageUpload)
71
 Vue.component('ImageUpload', ImageUpload)
63
 Vue.component('ImagePreview', ImagePreview)
72
 Vue.component('ImagePreview', ImagePreview)
73
+Vue.component('Tinymce', Tinymce)
64
 
74
 
65
 Vue.use(directive)
75
 Vue.use(directive)
66
 Vue.use(plugins)
76
 Vue.use(plugins)

+ 92 - 0
src/router/index.js

@@ -284,6 +284,97 @@ export const constantRoutes = [
284
         meta: { title: '个人中心', icon: 'user' }
284
         meta: { title: '个人中心', icon: 'user' }
285
       }
285
       }
286
     ]
286
     ]
287
+  },
288
+  {
289
+    path: '/flowable',
290
+    component: Layout,
291
+    hidden: true,
292
+    children: [
293
+      {
294
+        path: 'definition/model/',
295
+        component: () => import('@/views/flowable/definition/model'),
296
+        name: 'Model',
297
+        meta: { title: '流程设计', icon: '' }
298
+      }
299
+    ]
300
+  },
301
+  {
302
+    path: '/flowable',
303
+    component: Layout,
304
+    hidden: true,
305
+    children: [
306
+      {
307
+        path: 'task/finished/detail/index',
308
+        component: () => import('@/views/flowable/task/finished/detail/index'),
309
+        name: 'FinishedRecord',
310
+        meta: { title: '流程详情', icon: '' }
311
+      }
312
+    ]
313
+  },
314
+  {
315
+    path: '/flowable',
316
+    component: Layout,
317
+    hidden: true,
318
+    children: [
319
+      {
320
+        path: 'task/myProcess/detail/index',
321
+        component: () => import('@/views/flowable/task/myProcess/detail/index'),
322
+        name: 'MyProcessRecord',
323
+        meta: { title: '流程详情', icon: '' }
324
+      }
325
+    ]
326
+  },
327
+  {
328
+    path: '/flowable',
329
+    component: Layout,
330
+    hidden: true,
331
+    children: [
332
+      {
333
+        path: 'task/myProcess/send/index',
334
+        component: () => import('@/views/flowable/task/myProcess/send/index'),
335
+        name: 'SendRecord',
336
+        meta: { title: '流程发起', icon: '' }
337
+      }
338
+    ]
339
+  },
340
+  {
341
+    path: '/flowable',
342
+    component: Layout,
343
+    hidden: true,
344
+    children: [
345
+      {
346
+        path: 'task/todo/detail/index',
347
+        component: () => import('@/views/flowable/task/todo/detail/index'),
348
+        name: 'TodoRecord',
349
+        meta: { title: '流程处理', icon: '' }
350
+      }
351
+    ]
352
+  },
353
+  {
354
+    path: '/flowable',
355
+    component: Layout,
356
+    hidden: false,
357
+    children: [
358
+      {
359
+        path: 'task/flowForm/index',
360
+        component: () => import('@/views/flowable/task/flowForm/index'),
361
+        name: 'FlowForm',
362
+        meta: { title: '流程表单', icon: '' }
363
+      }
364
+    ]
365
+  },
366
+  {
367
+    path: '/tool',
368
+    component: Layout,
369
+    hidden: true,
370
+    children: [
371
+      {
372
+        path: 'build/index',
373
+        component: () => import('@/views/tool/build/index'),
374
+        name: 'FormBuild',
375
+        meta: { title: '表单配置', icon: '' }
376
+      }
377
+    ]
287
   }
378
   }
288
 ]
379
 ]
289
 
380
 
@@ -359,6 +450,7 @@ export const dynamicRoutes = [
359
       }
450
       }
360
     ]
451
     ]
361
   }
452
   }
453
+
362
 ]
454
 ]
363
 
455
 
364
 // 防止连续点击多次路由报错
456
 // 防止连续点击多次路由报错

+ 464 - 273
src/utils/generator/config.js

@@ -1,3 +1,4 @@
1
+// 表单属性【右面板】
1
 export const formConf = {
2
 export const formConf = {
2
   formRef: 'elForm',
3
   formRef: 'elForm',
3
   formModel: 'formData',
4
   formModel: 'formData',
@@ -11,144 +12,195 @@ export const formConf = {
11
   formBtns: true
12
   formBtns: true
12
 }
13
 }
13
 
14
 
15
+// 输入型组件 【左面板】
14
 export const inputComponents = [
16
 export const inputComponents = [
15
   {
17
   {
16
-    label: '单行文本',
17
-    tag: 'el-input',
18
-    tagIcon: 'input',
18
+    // 组件的自定义配置
19
+    __config__: {
20
+      label: '单行文本',
21
+      labelWidth: null,
22
+      showLabel: true,
23
+      changeTag: true,
24
+      tag: 'el-input',
25
+      tagIcon: 'input',
26
+      defaultValue: undefined,
27
+      required: true,
28
+      layout: 'colFormItem',
29
+      span: 24,
30
+      document: 'https://element.eleme.cn/#/zh-CN/component/input',
31
+      // 正则校验规则
32
+      regList: []
33
+    },
34
+    // 组件的插槽属性
35
+    __slot__: {
36
+      prepend: '',
37
+      append: ''
38
+    },
39
+    // 其余的为可直接写在组件标签上的属性
19
     placeholder: '请输入',
40
     placeholder: '请输入',
20
-    defaultValue: undefined,
21
-    span: 24,
22
-    labelWidth: null,
23
-    style: { width: '100%' },
41
+    style: {width: '100%'},
24
     clearable: true,
42
     clearable: true,
25
-    prepend: '',
26
-    append: '',
27
     'prefix-icon': '',
43
     'prefix-icon': '',
28
     'suffix-icon': '',
44
     'suffix-icon': '',
29
     maxlength: null,
45
     maxlength: null,
30
     'show-word-limit': false,
46
     'show-word-limit': false,
31
     readonly: false,
47
     readonly: false,
32
-    disabled: false,
33
-    required: true,
34
-    regList: [],
35
-    changeTag: true,
36
-    document: 'https://element.eleme.cn/#/zh-CN/component/input'
48
+    disabled: false
37
   },
49
   },
38
   {
50
   {
39
-    label: '多行文本',
40
-    tag: 'el-input',
41
-    tagIcon: 'textarea',
51
+    __config__: {
52
+      label: '多行文本',
53
+      labelWidth: null,
54
+      showLabel: true,
55
+      tag: 'el-input',
56
+      tagIcon: 'textarea',
57
+      defaultValue: undefined,
58
+      required: true,
59
+      layout: 'colFormItem',
60
+      span: 24,
61
+      regList: [],
62
+      changeTag: true,
63
+      document: 'https://element.eleme.cn/#/zh-CN/component/input'
64
+    },
42
     type: 'textarea',
65
     type: 'textarea',
43
     placeholder: '请输入',
66
     placeholder: '请输入',
44
-    defaultValue: undefined,
45
-    span: 24,
46
-    labelWidth: null,
47
     autosize: {
67
     autosize: {
48
       minRows: 4,
68
       minRows: 4,
49
       maxRows: 4
69
       maxRows: 4
50
     },
70
     },
51
-    style: { width: '100%' },
71
+    style: {width: '100%'},
52
     maxlength: null,
72
     maxlength: null,
53
     'show-word-limit': false,
73
     'show-word-limit': false,
54
     readonly: false,
74
     readonly: false,
55
-    disabled: false,
56
-    required: true,
57
-    regList: [],
58
-    changeTag: true,
59
-    document: 'https://element.eleme.cn/#/zh-CN/component/input'
75
+    disabled: false
60
   },
76
   },
61
   {
77
   {
62
-    label: '密码',
63
-    tag: 'el-input',
64
-    tagIcon: 'password',
78
+    __config__: {
79
+      label: '密码',
80
+      showLabel: true,
81
+      labelWidth: null,
82
+      changeTag: true,
83
+      tag: 'el-input',
84
+      tagIcon: 'password',
85
+      defaultValue: undefined,
86
+      layout: 'colFormItem',
87
+      span: 24,
88
+      required: true,
89
+      regList: [],
90
+      document: 'https://element.eleme.cn/#/zh-CN/component/input'
91
+    },
92
+    __slot__: {
93
+      prepend: '',
94
+      append: ''
95
+    },
65
     placeholder: '请输入',
96
     placeholder: '请输入',
66
-    defaultValue: undefined,
67
-    span: 24,
68
     'show-password': true,
97
     'show-password': true,
69
-    labelWidth: null,
70
-    style: { width: '100%' },
98
+    style: {width: '100%'},
71
     clearable: true,
99
     clearable: true,
72
-    prepend: '',
73
-    append: '',
74
     'prefix-icon': '',
100
     'prefix-icon': '',
75
     'suffix-icon': '',
101
     'suffix-icon': '',
76
     maxlength: null,
102
     maxlength: null,
77
     'show-word-limit': false,
103
     'show-word-limit': false,
78
     readonly: false,
104
     readonly: false,
79
-    disabled: false,
80
-    required: true,
81
-    regList: [],
82
-    changeTag: true,
83
-    document: 'https://element.eleme.cn/#/zh-CN/component/input'
105
+    disabled: false
84
   },
106
   },
85
   {
107
   {
86
-    label: '计数器',
87
-    tag: 'el-input-number',
88
-    tagIcon: 'number',
108
+    __config__: {
109
+      label: '计数器',
110
+      showLabel: true,
111
+      changeTag: true,
112
+      labelWidth: null,
113
+      tag: 'el-input-number',
114
+      tagIcon: 'number',
115
+      defaultValue: undefined,
116
+      span: 24,
117
+      layout: 'colFormItem',
118
+      required: true,
119
+      regList: [],
120
+      document: 'https://element.eleme.cn/#/zh-CN/component/input-number'
121
+    },
89
     placeholder: '',
122
     placeholder: '',
90
-    defaultValue: undefined,
91
-    span: 24,
92
-    labelWidth: null,
93
     min: undefined,
123
     min: undefined,
94
     max: undefined,
124
     max: undefined,
95
-    step: undefined,
125
+    step: 1,
96
     'step-strictly': false,
126
     'step-strictly': false,
97
     precision: undefined,
127
     precision: undefined,
98
     'controls-position': '',
128
     'controls-position': '',
99
-    disabled: false,
100
-    required: true,
101
-    regList: [],
102
-    changeTag: true,
103
-    document: 'https://element.eleme.cn/#/zh-CN/component/input-number'
129
+    disabled: false
130
+  },
131
+  {
132
+    __config__: {
133
+      label: '编辑器',
134
+      showLabel: true,
135
+      changeTag: true,
136
+      labelWidth: null,
137
+      tag: 'tinymce',
138
+      tagIcon: 'rich-text',
139
+      defaultValue: null,
140
+      span: 24,
141
+      layout: 'colFormItem',
142
+      required: true,
143
+      regList: [],
144
+      document: 'http://tinymce.ax-z.cn'
145
+    },
146
+    placeholder: '请输入',
147
+    height: 300, // 编辑器高度
148
+    branding: false // 隐藏右下角品牌烙印
104
   }
149
   }
105
 ]
150
 ]
106
 
151
 
152
+// 选择型组件 【左面板】
107
 export const selectComponents = [
153
 export const selectComponents = [
108
   {
154
   {
109
-    label: '下拉选择',
110
-    tag: 'el-select',
111
-    tagIcon: 'select',
155
+    __config__: {
156
+      label: '下拉选择',
157
+      showLabel: true,
158
+      labelWidth: null,
159
+      tag: 'el-select',
160
+      tagIcon: 'select',
161
+      layout: 'colFormItem',
162
+      span: 24,
163
+      required: true,
164
+      regList: [],
165
+      changeTag: true,
166
+      document: 'https://element.eleme.cn/#/zh-CN/component/select'
167
+    },
168
+    __slot__: {
169
+      options: [{
170
+        label: '选项一',
171
+        value: 1
172
+      }, {
173
+        label: '选项二',
174
+        value: 2
175
+      }]
176
+    },
112
     placeholder: '请选择',
177
     placeholder: '请选择',
113
-    defaultValue: undefined,
114
-    span: 24,
115
-    labelWidth: null,
116
-    style: { width: '100%' },
178
+    style: {width: '100%'},
117
     clearable: true,
179
     clearable: true,
118
     disabled: false,
180
     disabled: false,
119
-    required: true,
120
     filterable: false,
181
     filterable: false,
121
-    multiple: false,
122
-    options: [{
123
-      label: '选项一',
124
-      value: 1
125
-    }, {
126
-      label: '选项二',
127
-      value: 2
128
-    }],
129
-    regList: [],
130
-    changeTag: true,
131
-    document: 'https://element.eleme.cn/#/zh-CN/component/select'
182
+    multiple: false
132
   },
183
   },
133
   {
184
   {
134
-    label: '级联选择',
135
-    tag: 'el-cascader',
136
-    tagIcon: 'cascader',
137
-    placeholder: '请选择',
138
-    defaultValue: [],
139
-    span: 24,
140
-    labelWidth: null,
141
-    style: { width: '100%' },
142
-    props: {
143
-      props: {
144
-        multiple: false
145
-      }
185
+    __config__: {
186
+      label: '级联选择',
187
+      url: 'https://www.fastmock.site/mock/f8d7a54fb1e60561e2f720d5a810009d/fg/cascaderList',
188
+      method: 'get',
189
+      dataPath: 'list',
190
+      dataConsumer: 'options',
191
+      showLabel: true,
192
+      labelWidth: null,
193
+      tag: 'el-cascader',
194
+      tagIcon: 'cascader',
195
+      layout: 'colFormItem',
196
+      defaultValue: [],
197
+      dataType: 'dynamic',
198
+      span: 24,
199
+      required: true,
200
+      regList: [],
201
+      changeTag: true,
202
+      document: 'https://element.eleme.cn/#/zh-CN/component/cascader'
146
     },
203
     },
147
-    'show-all-levels': true,
148
-    disabled: false,
149
-    clearable: true,
150
-    filterable: false,
151
-    required: true,
152
     options: [{
204
     options: [{
153
       id: 1,
205
       id: 1,
154
       value: 1,
206
       value: 1,
@@ -159,280 +211,419 @@ export const selectComponents = [
159
         label: '选项1-1'
211
         label: '选项1-1'
160
       }]
212
       }]
161
     }],
213
     }],
162
-    dataType: 'dynamic',
163
-    labelKey: 'label',
164
-    valueKey: 'value',
165
-    childrenKey: 'children',
166
-    separator: '/',
167
-    regList: [],
168
-    changeTag: true,
169
-    document: 'https://element.eleme.cn/#/zh-CN/component/cascader'
214
+    placeholder: '请选择',
215
+    style: {width: '100%'},
216
+    props: {
217
+      props: {
218
+        multiple: false,
219
+        label: 'label',
220
+        value: 'value',
221
+        children: 'children'
222
+      }
223
+    },
224
+    'show-all-levels': true,
225
+    disabled: false,
226
+    clearable: true,
227
+    filterable: false,
228
+    separator: '/'
170
   },
229
   },
171
   {
230
   {
172
-    label: '单选框组',
173
-    tag: 'el-radio-group',
174
-    tagIcon: 'radio',
175
-    defaultValue: undefined,
176
-    span: 24,
177
-    labelWidth: null,
231
+    __config__: {
232
+      label: '单选框组',
233
+      labelWidth: null,
234
+      showLabel: true,
235
+      tag: 'el-radio-group',
236
+      tagIcon: 'radio',
237
+      changeTag: true,
238
+      defaultValue: undefined,
239
+      layout: 'colFormItem',
240
+      span: 24,
241
+      optionType: 'default',
242
+      regList: [],
243
+      required: true,
244
+      border: false,
245
+      document: 'https://element.eleme.cn/#/zh-CN/component/radio'
246
+    },
247
+    __slot__: {
248
+      options: [{
249
+        label: '选项一',
250
+        value: 1
251
+      }, {
252
+        label: '选项二',
253
+        value: 2
254
+      }]
255
+    },
178
     style: {},
256
     style: {},
179
-    optionType: 'default',
180
-    border: false,
181
     size: 'medium',
257
     size: 'medium',
182
-    disabled: false,
183
-    required: true,
184
-    options: [{
185
-      label: '选项一',
186
-      value: 1
187
-    }, {
188
-      label: '选项二',
189
-      value: 2
190
-    }],
191
-    regList: [],
192
-    changeTag: true,
193
-    document: 'https://element.eleme.cn/#/zh-CN/component/radio'
258
+    disabled: false
194
   },
259
   },
195
   {
260
   {
196
-    label: '多选框组',
197
-    tag: 'el-checkbox-group',
198
-    tagIcon: 'checkbox',
199
-    defaultValue: [],
200
-    span: 24,
201
-    labelWidth: null,
261
+    __config__: {
262
+      label: '多选框组',
263
+      tag: 'el-checkbox-group',
264
+      tagIcon: 'checkbox',
265
+      defaultValue: [],
266
+      span: 24,
267
+      showLabel: true,
268
+      labelWidth: null,
269
+      layout: 'colFormItem',
270
+      optionType: 'default',
271
+      required: true,
272
+      regList: [],
273
+      changeTag: true,
274
+      border: false,
275
+      document: 'https://element.eleme.cn/#/zh-CN/component/checkbox'
276
+    },
277
+    __slot__: {
278
+      options: [{
279
+        label: '选项一',
280
+        value: 1
281
+      }, {
282
+        label: '选项二',
283
+        value: 2
284
+      }]
285
+    },
202
     style: {},
286
     style: {},
203
-    optionType: 'default',
204
-    border: false,
205
     size: 'medium',
287
     size: 'medium',
206
-    disabled: false,
207
-    required: true,
208
-    options: [{
209
-      label: '选项一',
210
-      value: 1
211
-    }, {
212
-      label: '选项二',
213
-      value: 2
214
-    }],
215
-    regList: [],
216
-    changeTag: true,
217
-    document: 'https://element.eleme.cn/#/zh-CN/component/checkbox'
288
+    min: null,
289
+    max: null,
290
+    disabled: false
218
   },
291
   },
219
   {
292
   {
220
-    label: '开关',
221
-    tag: 'el-switch',
222
-    tagIcon: 'switch',
223
-    defaultValue: false,
224
-    span: 24,
225
-    labelWidth: null,
293
+    __config__: {
294
+      label: '开关',
295
+      tag: 'el-switch',
296
+      tagIcon: 'switch',
297
+      defaultValue: false,
298
+      span: 24,
299
+      showLabel: true,
300
+      labelWidth: null,
301
+      layout: 'colFormItem',
302
+      required: true,
303
+      regList: [],
304
+      changeTag: true,
305
+      document: 'https://element.eleme.cn/#/zh-CN/component/switch'
306
+    },
226
     style: {},
307
     style: {},
227
     disabled: false,
308
     disabled: false,
228
-    required: true,
229
     'active-text': '',
309
     'active-text': '',
230
     'inactive-text': '',
310
     'inactive-text': '',
231
     'active-color': null,
311
     'active-color': null,
232
     'inactive-color': null,
312
     'inactive-color': null,
233
     'active-value': true,
313
     'active-value': true,
234
-    'inactive-value': false,
235
-    regList: [],
236
-    changeTag: true,
237
-    document: 'https://element.eleme.cn/#/zh-CN/component/switch'
314
+    'inactive-value': false
238
   },
315
   },
239
   {
316
   {
240
-    label: '滑块',
241
-    tag: 'el-slider',
242
-    tagIcon: 'slider',
243
-    defaultValue: null,
244
-    span: 24,
245
-    labelWidth: null,
317
+    __config__: {
318
+      label: '滑块',
319
+      tag: 'el-slider',
320
+      tagIcon: 'slider',
321
+      defaultValue: null,
322
+      span: 24,
323
+      showLabel: true,
324
+      layout: 'colFormItem',
325
+      labelWidth: null,
326
+      required: true,
327
+      regList: [],
328
+      changeTag: true,
329
+      document: 'https://element.eleme.cn/#/zh-CN/component/slider'
330
+    },
246
     disabled: false,
331
     disabled: false,
247
-    required: true,
248
     min: 0,
332
     min: 0,
249
     max: 100,
333
     max: 100,
250
     step: 1,
334
     step: 1,
251
     'show-stops': false,
335
     'show-stops': false,
252
-    range: false,
253
-    regList: [],
254
-    changeTag: true,
255
-    document: 'https://element.eleme.cn/#/zh-CN/component/slider'
336
+    range: false
256
   },
337
   },
257
   {
338
   {
258
-    label: '时间选择',
259
-    tag: 'el-time-picker',
260
-    tagIcon: 'time',
339
+    __config__: {
340
+      label: '时间选择',
341
+      tag: 'el-time-picker',
342
+      tagIcon: 'time',
343
+      defaultValue: null,
344
+      span: 24,
345
+      showLabel: true,
346
+      layout: 'colFormItem',
347
+      labelWidth: null,
348
+      required: true,
349
+      regList: [],
350
+      changeTag: true,
351
+      document: 'https://element.eleme.cn/#/zh-CN/component/time-picker'
352
+    },
261
     placeholder: '请选择',
353
     placeholder: '请选择',
262
-    defaultValue: null,
263
-    span: 24,
264
-    labelWidth: null,
265
-    style: { width: '100%' },
354
+    style: {width: '100%'},
266
     disabled: false,
355
     disabled: false,
267
     clearable: true,
356
     clearable: true,
268
-    required: true,
269
     'picker-options': {
357
     'picker-options': {
270
       selectableRange: '00:00:00-23:59:59'
358
       selectableRange: '00:00:00-23:59:59'
271
     },
359
     },
272
     format: 'HH:mm:ss',
360
     format: 'HH:mm:ss',
273
-    'value-format': 'HH:mm:ss',
274
-    regList: [],
275
-    changeTag: true,
276
-    document: 'https://element.eleme.cn/#/zh-CN/component/time-picker'
361
+    'value-format': 'HH:mm:ss'
277
   },
362
   },
278
   {
363
   {
279
-    label: '时间范围',
280
-    tag: 'el-time-picker',
281
-    tagIcon: 'time-range',
282
-    defaultValue: null,
283
-    span: 24,
284
-    labelWidth: null,
285
-    style: { width: '100%' },
364
+    __config__: {
365
+      label: '时间范围',
366
+      tag: 'el-time-picker',
367
+      tagIcon: 'time-range',
368
+      span: 24,
369
+      showLabel: true,
370
+      labelWidth: null,
371
+      layout: 'colFormItem',
372
+      defaultValue: null,
373
+      required: true,
374
+      regList: [],
375
+      changeTag: true,
376
+      document: 'https://element.eleme.cn/#/zh-CN/component/time-picker'
377
+    },
378
+    style: {width: '100%'},
286
     disabled: false,
379
     disabled: false,
287
     clearable: true,
380
     clearable: true,
288
-    required: true,
289
     'is-range': true,
381
     'is-range': true,
290
     'range-separator': '至',
382
     'range-separator': '至',
291
     'start-placeholder': '开始时间',
383
     'start-placeholder': '开始时间',
292
     'end-placeholder': '结束时间',
384
     'end-placeholder': '结束时间',
293
     format: 'HH:mm:ss',
385
     format: 'HH:mm:ss',
294
-    'value-format': 'HH:mm:ss',
295
-    regList: [],
296
-    changeTag: true,
297
-    document: 'https://element.eleme.cn/#/zh-CN/component/time-picker'
386
+    'value-format': 'HH:mm:ss'
298
   },
387
   },
299
   {
388
   {
300
-    label: '日期选择',
301
-    tag: 'el-date-picker',
302
-    tagIcon: 'date',
389
+    __config__: {
390
+      label: '日期选择',
391
+      tag: 'el-date-picker',
392
+      tagIcon: 'date',
393
+      defaultValue: null,
394
+      showLabel: true,
395
+      labelWidth: null,
396
+      span: 24,
397
+      layout: 'colFormItem',
398
+      required: true,
399
+      regList: [],
400
+      changeTag: true,
401
+      document: 'https://element.eleme.cn/#/zh-CN/component/date-picker'
402
+    },
303
     placeholder: '请选择',
403
     placeholder: '请选择',
304
-    defaultValue: null,
305
     type: 'date',
404
     type: 'date',
306
-    span: 24,
307
-    labelWidth: null,
308
-    style: { width: '100%' },
405
+    style: {width: '100%'},
309
     disabled: false,
406
     disabled: false,
310
     clearable: true,
407
     clearable: true,
311
-    required: true,
312
     format: 'yyyy-MM-dd',
408
     format: 'yyyy-MM-dd',
313
     'value-format': 'yyyy-MM-dd',
409
     'value-format': 'yyyy-MM-dd',
314
-    readonly: false,
315
-    regList: [],
316
-    changeTag: true,
317
-    document: 'https://element.eleme.cn/#/zh-CN/component/date-picker'
410
+    readonly: false
318
   },
411
   },
319
   {
412
   {
320
-    label: '日期范围',
321
-    tag: 'el-date-picker',
322
-    tagIcon: 'date-range',
323
-    defaultValue: null,
324
-    span: 24,
325
-    labelWidth: null,
326
-    style: { width: '100%' },
413
+    __config__: {
414
+      label: '日期范围',
415
+      tag: 'el-date-picker',
416
+      tagIcon: 'date-range',
417
+      defaultValue: null,
418
+      span: 24,
419
+      showLabel: true,
420
+      labelWidth: null,
421
+      required: true,
422
+      layout: 'colFormItem',
423
+      regList: [],
424
+      changeTag: true,
425
+      document: 'https://element.eleme.cn/#/zh-CN/component/date-picker'
426
+    },
427
+    style: {width: '100%'},
327
     type: 'daterange',
428
     type: 'daterange',
328
     'range-separator': '至',
429
     'range-separator': '至',
329
     'start-placeholder': '开始日期',
430
     'start-placeholder': '开始日期',
330
     'end-placeholder': '结束日期',
431
     'end-placeholder': '结束日期',
331
     disabled: false,
432
     disabled: false,
332
     clearable: true,
433
     clearable: true,
333
-    required: true,
334
     format: 'yyyy-MM-dd',
434
     format: 'yyyy-MM-dd',
335
     'value-format': 'yyyy-MM-dd',
435
     'value-format': 'yyyy-MM-dd',
336
-    readonly: false,
337
-    regList: [],
338
-    changeTag: true,
339
-    document: 'https://element.eleme.cn/#/zh-CN/component/date-picker'
436
+    readonly: false
340
   },
437
   },
341
   {
438
   {
342
-    label: '评分',
343
-    tag: 'el-rate',
344
-    tagIcon: 'rate',
345
-    defaultValue: 0,
346
-    span: 24,
347
-    labelWidth: null,
439
+    __config__: {
440
+      label: '评分',
441
+      tag: 'el-rate',
442
+      tagIcon: 'rate',
443
+      defaultValue: 0,
444
+      span: 24,
445
+      showLabel: true,
446
+      labelWidth: null,
447
+      layout: 'colFormItem',
448
+      required: true,
449
+      regList: [],
450
+      changeTag: true,
451
+      document: 'https://element.eleme.cn/#/zh-CN/component/rate'
452
+    },
348
     style: {},
453
     style: {},
349
     max: 5,
454
     max: 5,
350
     'allow-half': false,
455
     'allow-half': false,
351
     'show-text': false,
456
     'show-text': false,
352
     'show-score': false,
457
     'show-score': false,
353
-    disabled: false,
354
-    required: true,
355
-    regList: [],
356
-    changeTag: true,
357
-    document: 'https://element.eleme.cn/#/zh-CN/component/rate'
458
+    disabled: false
358
   },
459
   },
359
   {
460
   {
360
-    label: '颜色选择',
361
-    tag: 'el-color-picker',
362
-    tagIcon: 'color',
363
-    defaultValue: null,
364
-    labelWidth: null,
461
+    __config__: {
462
+      label: '颜色选择',
463
+      tag: 'el-color-picker',
464
+      tagIcon: 'color',
465
+      span: 24,
466
+      defaultValue: null,
467
+      showLabel: true,
468
+      labelWidth: null,
469
+      layout: 'colFormItem',
470
+      required: true,
471
+      regList: [],
472
+      changeTag: true,
473
+      document: 'https://element.eleme.cn/#/zh-CN/component/color-picker'
474
+    },
365
     'show-alpha': false,
475
     'show-alpha': false,
366
     'color-format': '',
476
     'color-format': '',
367
     disabled: false,
477
     disabled: false,
368
-    required: true,
369
-    size: 'medium',
370
-    regList: [],
371
-    changeTag: true,
372
-    document: 'https://element.eleme.cn/#/zh-CN/component/color-picker'
478
+    size: 'medium'
373
   },
479
   },
374
   {
480
   {
375
-    label: '上传',
376
-    tag: 'el-upload',
377
-    tagIcon: 'upload',
378
-    action: 'https://jsonplaceholder.typicode.com/posts/',
379
-    defaultValue: null,
380
-    labelWidth: null,
481
+    __config__: {
482
+      label: '上传',
483
+      tag: 'el-upload',
484
+      tagIcon: 'upload',
485
+      layout: 'colFormItem',
486
+      defaultValue: null,
487
+      showLabel: true,
488
+      labelWidth: null,
489
+      required: true,
490
+      span: 24,
491
+      showTip: false,
492
+      buttonText: '点击上传',
493
+      regList: [],
494
+      changeTag: true,
495
+      fileSize: 2,
496
+      sizeUnit: 'MB',
497
+      document: 'https://element.eleme.cn/#/zh-CN/component/upload'
498
+    },
499
+    __slot__: {
500
+      'list-type': true
501
+    },
502
+    action: 'http://localhost:8080/file/upload',
381
     disabled: false,
503
     disabled: false,
382
-    required: true,
383
     accept: '',
504
     accept: '',
384
     name: 'file',
505
     name: 'file',
385
     'auto-upload': true,
506
     'auto-upload': true,
386
-    showTip: false,
387
-    buttonText: '点击上传',
388
-    fileSize: 2,
389
-    sizeUnit: 'MB',
390
     'list-type': 'text',
507
     'list-type': 'text',
391
-    multiple: false,
392
-    regList: [],
393
-    changeTag: true,
394
-    document: 'https://element.eleme.cn/#/zh-CN/component/upload'
508
+    multiple: false
395
   }
509
   }
396
 ]
510
 ]
397
 
511
 
512
+// 布局型组件 【左面板】
398
 export const layoutComponents = [
513
 export const layoutComponents = [
399
   {
514
   {
400
-    layout: 'rowFormItem',
401
-    tagIcon: 'row',
515
+    __config__: {
516
+      layout: 'rowFormItem',
517
+      tagIcon: 'row',
518
+      label: '行容器',
519
+      layoutTree: true,
520
+      document: 'https://element.eleme.cn/#/zh-CN/component/layout#row-attributes'
521
+    },
402
     type: 'default',
522
     type: 'default',
403
     justify: 'start',
523
     justify: 'start',
404
-    align: 'top',
405
-    label: '行容器',
406
-    layoutTree: true,
407
-    children: [],
408
-    document: 'https://element.eleme.cn/#/zh-CN/component/layout'
524
+    align: 'top'
409
   },
525
   },
410
   {
526
   {
411
-    layout: 'colFormItem',
412
-    label: '按钮',
413
-    changeTag: true,
414
-    labelWidth: null,
415
-    tag: 'el-button',
416
-    tagIcon: 'button',
417
-    span: 24,
418
-    default: '主要按钮',
527
+    __config__: {
528
+      label: '按钮',
529
+      showLabel: true,
530
+      changeTag: true,
531
+      labelWidth: null,
532
+      tag: 'el-button',
533
+      tagIcon: 'button',
534
+      span: 24,
535
+      layout: 'colFormItem',
536
+      document: 'https://element.eleme.cn/#/zh-CN/component/button'
537
+    },
538
+    __slot__: {
539
+      default: '主要按钮'
540
+    },
419
     type: 'primary',
541
     type: 'primary',
420
     icon: 'el-icon-search',
542
     icon: 'el-icon-search',
543
+    round: false,
421
     size: 'medium',
544
     size: 'medium',
422
-    disabled: false,
423
-    document: 'https://element.eleme.cn/#/zh-CN/component/button'
424
-  }
545
+    plain: false,
546
+    circle: false,
547
+    disabled: false
548
+  },
549
+  // {
550
+  //   __config__: {
551
+  //     layout: 'colFormItem',
552
+  //     tagIcon: 'table',
553
+  //     tag: 'el-table',
554
+  //     document: 'https://element.eleme.cn/#/zh-CN/component/table',
555
+  //     span: 24,
556
+  //     formId: 101,
557
+  //     renderKey: 1595761764203,
558
+  //     componentName: 'row101',
559
+  //     showLabel: true,
560
+  //     changeTag: true,
561
+  //     labelWidth: null,
562
+  //     label: '表格[开发中]',
563
+  //     dataType: 'dynamic',
564
+  //     method: 'get',
565
+  //     dataPath: 'list',
566
+  //     dataConsumer: 'data',
567
+  //     url: 'https://www.fastmock.site/mock/f8d7a54fb1e60561e2f720d5a810009d/fg/tableData',
568
+  //     children: [{
569
+  //       __config__: {
570
+  //         layout: 'raw',
571
+  //         tag: 'el-table-column',
572
+  //         renderKey: 15957617660153
573
+  //       },
574
+  //       prop: 'date',
575
+  //       label: '日期'
576
+  //     }, {
577
+  //       __config__: {
578
+  //         layout: 'raw',
579
+  //         tag: 'el-table-column',
580
+  //         renderKey: 15957617660152
581
+  //       },
582
+  //       prop: 'address',
583
+  //       label: '地址'
584
+  //     }, {
585
+  //       __config__: {
586
+  //         layout: 'raw',
587
+  //         tag: 'el-table-column',
588
+  //         renderKey: 15957617660151
589
+  //       },
590
+  //       prop: 'name',
591
+  //       label: '名称'
592
+  //     }, {
593
+  //       __config__: {
594
+  //         layout: 'raw',
595
+  //         tag: 'el-table-column',
596
+  //         renderKey: 1595774496335,
597
+  //         children: [
598
+  //           {
599
+  //             __config__: {
600
+  //               label: '按钮',
601
+  //               tag: 'el-button',
602
+  //               tagIcon: 'button',
603
+  //               layout: 'raw',
604
+  //               renderKey: 1595779809901
605
+  //             },
606
+  //             __slot__: {
607
+  //               default: '主要按钮'
608
+  //             },
609
+  //             type: 'primary',
610
+  //             icon: 'el-icon-search',
611
+  //             round: false,
612
+  //             size: 'medium'
613
+  //           }
614
+  //         ]
615
+  //       },
616
+  //       label: '操作'
617
+  //     }]
618
+  //   },
619
+  //   data: [],
620
+  //   directives: [{
621
+  //     name: 'loading',
622
+  //     value: true
623
+  //   }],
624
+  //   border: true,
625
+  //   type: 'default',
626
+  //   justify: 'start',
627
+  //   align: 'top'
628
+  // }
425
 ]
629
 ]
426
-
427
-// 组件rule的触发方式,无触发方式的组件不生成rule
428
-export const trigger = {
429
-  'el-input': 'blur',
430
-  'el-input-number': 'blur',
431
-  'el-select': 'change',
432
-  'el-radio-group': 'change',
433
-  'el-checkbox-group': 'change',
434
-  'el-cascader': 'change',
435
-  'el-time-picker': 'change',
436
-  'el-date-picker': 'change',
437
-  'el-rate': 'change'
438
-}

+ 37 - 0
src/utils/generator/drawingDefalut.js

@@ -0,0 +1,37 @@
1
+export default [
2
+  {
3
+    __config__: {
4
+      label: '单行文本',
5
+      labelWidth: null,
6
+      showLabel: true,
7
+      changeTag: true,
8
+      tag: 'el-input',
9
+      tagIcon: 'input',
10
+      defaultValue: undefined,
11
+      required: true,
12
+      layout: 'colFormItem',
13
+      span: 24,
14
+      document: 'https://element.eleme.cn/#/zh-CN/component/input',
15
+      // 正则校验规则
16
+      regList: [{
17
+        pattern: '/^1(3|4|5|7|8|9)\\d{9}$/',
18
+        message: '手机号格式错误'
19
+      }]
20
+    },
21
+    // 组件的插槽属性
22
+    __slot__: {
23
+      prepend: '',
24
+      append: ''
25
+    },
26
+    __vModel__: 'mobile',
27
+    placeholder: '请输入手机号',
28
+    style: { width: '100%' },
29
+    clearable: true,
30
+    'prefix-icon': 'el-icon-mobile',
31
+    'suffix-icon': '',
32
+    maxlength: 11,
33
+    'show-word-limit': true,
34
+    readonly: false,
35
+    disabled: false
36
+  }
37
+]

+ 0 - 29
src/utils/generator/drawingDefault.js

@@ -1,29 +0,0 @@
1
-export default [
2
-  {
3
-    layout: 'colFormItem',
4
-    tagIcon: 'input',
5
-    label: '手机号',
6
-    vModel: 'mobile',
7
-    formId: 6,
8
-    tag: 'el-input',
9
-    placeholder: '请输入手机号',
10
-    defaultValue: '',
11
-    span: 24,
12
-    style: { width: '100%' },
13
-    clearable: true,
14
-    prepend: '',
15
-    append: '',
16
-    'prefix-icon': 'el-icon-mobile',
17
-    'suffix-icon': '',
18
-    maxlength: 11,
19
-    'show-word-limit': true,
20
-    readonly: false,
21
-    disabled: false,
22
-    required: true,
23
-    changeTag: true,
24
-    regList: [{
25
-      pattern: '/^1(3|4|5|7|8|9)\\d{9}$/',
26
-      message: '手机号格式错误'
27
-    }]
28
-  }
29
-]

+ 57 - 20
src/utils/index.js

@@ -5,12 +5,12 @@ import { parseTime } from './ruoyi'
5
  */
5
  */
6
 export function formatDate(cellValue) {
6
 export function formatDate(cellValue) {
7
   if (cellValue == null || cellValue == "") return "";
7
   if (cellValue == null || cellValue == "") return "";
8
-  var date = new Date(cellValue) 
8
+  var date = new Date(cellValue)
9
   var year = date.getFullYear()
9
   var year = date.getFullYear()
10
   var month = date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1
10
   var month = date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1
11
-  var day = date.getDate() < 10 ? '0' + date.getDate() : date.getDate() 
12
-  var hours = date.getHours() < 10 ? '0' + date.getHours() : date.getHours() 
13
-  var minutes = date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes() 
11
+  var day = date.getDate() < 10 ? '0' + date.getDate() : date.getDate()
12
+  var hours = date.getHours() < 10 ? '0' + date.getHours() : date.getHours()
13
+  var minutes = date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes()
14
   var seconds = date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds()
14
   var seconds = date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds()
15
   return year + '-' + month + '-' + day + ' ' + hours + ':' + minutes + ':' + seconds
15
   return year + '-' + month + '-' + day + ' ' + hours + ':' + minutes + ':' + seconds
16
 }
16
 }
@@ -257,20 +257,20 @@ export function debounce(func, wait, immediate) {
257
  * @param {Object} source
257
  * @param {Object} source
258
  * @returns {Object}
258
  * @returns {Object}
259
  */
259
  */
260
-export function deepClone(source) {
261
-  if (!source && typeof source !== 'object') {
262
-    throw new Error('error arguments', 'deepClone')
263
-  }
264
-  const targetObj = source.constructor === Array ? [] : {}
265
-  Object.keys(source).forEach(keys => {
266
-    if (source[keys] && typeof source[keys] === 'object') {
267
-      targetObj[keys] = deepClone(source[keys])
268
-    } else {
269
-      targetObj[keys] = source[keys]
270
-    }
271
-  })
272
-  return targetObj
273
-}
260
+// export function deepClone(source) {
261
+//   if (!source && typeof source !== 'object') {
262
+//     throw new Error('error arguments', 'deepClone')
263
+//   }
264
+//   const targetObj = source.constructor === Array ? [] : {}
265
+//   Object.keys(source).forEach(keys => {
266
+//     if (source[keys] && typeof source[keys] === 'object') {
267
+//       targetObj[keys] = deepClone(source[keys])
268
+//     } else {
269
+//       targetObj[keys] = source[keys]
270
+//     }
271
+//   })
272
+//   return targetObj
273
+// }
274
 
274
 
275
 /**
275
 /**
276
  * @param {Array} arr
276
  * @param {Array} arr
@@ -330,7 +330,7 @@ export function makeMap(str, expectsLowerCase) {
330
     ? val => map[val.toLowerCase()]
330
     ? val => map[val.toLowerCase()]
331
     : val => map[val]
331
     : val => map[val]
332
 }
332
 }
333
- 
333
+
334
 export const exportDefault = 'export default '
334
 export const exportDefault = 'export default '
335
 
335
 
336
 export const beautifierConf = {
336
 export const beautifierConf = {
@@ -387,4 +387,41 @@ export function camelCase(str) {
387
 export function isNumberStr(str) {
387
 export function isNumberStr(str) {
388
   return /^[+-]?(0|([1-9]\d*))(\.\d+)?$/g.test(str)
388
   return /^[+-]?(0|([1-9]\d*))(\.\d+)?$/g.test(str)
389
 }
389
 }
390
- 
390
+// 深拷贝对象
391
+export function deepClone(obj) {
392
+  const _toString = Object.prototype.toString
393
+
394
+  // null, undefined, non-object, function
395
+  if (!obj || typeof obj !== 'object') {
396
+    return obj
397
+  }
398
+
399
+  // DOM Node
400
+  if (obj.nodeType && 'cloneNode' in obj) {
401
+    return obj.cloneNode(true)
402
+  }
403
+
404
+  // Date
405
+  if (_toString.call(obj) === '[object Date]') {
406
+    return new Date(obj.getTime())
407
+  }
408
+
409
+  // RegExp
410
+  if (_toString.call(obj) === '[object RegExp]') {
411
+    const flags = []
412
+    if (obj.global) { flags.push('g') }
413
+    if (obj.multiline) { flags.push('m') }
414
+    if (obj.ignoreCase) { flags.push('i') }
415
+
416
+    return new RegExp(obj.source, flags.join(''))
417
+  }
418
+
419
+  const result = Array.isArray(obj) ? [] : obj.constructor ? new obj.constructor() : {}
420
+
421
+  for (const key in obj) {
422
+    result[key] = deepClone(obj[key])
423
+  }
424
+
425
+  return result
426
+}
427
+

+ 4 - 8
src/utils/permission.js

@@ -15,10 +15,8 @@ export function checkPermi(value) {
15
       return all_permission === permission || permissionDatas.includes(permission)
15
       return all_permission === permission || permissionDatas.includes(permission)
16
     })
16
     })
17
 
17
 
18
-    if (!hasPermission) {
19
-      return false
20
-    }
21
-    return true
18
+    return hasPermission;
19
+
22
   } else {
20
   } else {
23
     console.error(`need roles! Like checkPermi="['system:user:add','system:user:edit']"`)
21
     console.error(`need roles! Like checkPermi="['system:user:add','system:user:edit']"`)
24
     return false
22
     return false
@@ -40,10 +38,8 @@ export function checkRole(value) {
40
       return super_admin === role || permissionRoles.includes(role)
38
       return super_admin === role || permissionRoles.includes(role)
41
     })
39
     })
42
 
40
 
43
-    if (!hasRole) {
44
-      return false
45
-    }
46
-    return true
41
+    return hasRole;
42
+
47
   } else {
43
   } else {
48
     console.error(`need roles! Like checkRole="['admin','editor']"`)
44
     console.error(`need roles! Like checkRole="['admin','editor']"`)
49
     return false
45
     return false

+ 6 - 2
src/views/tool/build/CodeTypeDialog.vue

@@ -41,7 +41,7 @@
41
         <el-button @click="close">
41
         <el-button @click="close">
42
           取消
42
           取消
43
         </el-button>
43
         </el-button>
44
-        <el-button type="primary" @click="handleConfirm">
44
+        <el-button type="primary" @click="handelConfirm">
45
           确定
45
           确定
46
         </el-button>
46
         </el-button>
47
       </div>
47
       </div>
@@ -94,7 +94,7 @@ export default {
94
     close(e) {
94
     close(e) {
95
       this.$emit('update:visible', false)
95
       this.$emit('update:visible', false)
96
     },
96
     },
97
-    handleConfirm() {
97
+    handelConfirm() {
98
       this.$refs.elForm.validate(valid => {
98
       this.$refs.elForm.validate(valid => {
99
         if (!valid) return
99
         if (!valid) return
100
         this.$emit('confirm', { ...this.formData })
100
         this.$emit('confirm', { ...this.formData })
@@ -104,3 +104,7 @@ export default {
104
   }
104
   }
105
 }
105
 }
106
 </script>
106
 </script>
107
+
108
+<style lang="scss" scoped>
109
+
110
+</style>

+ 55 - 35
src/views/tool/build/DraggableItem.vue

@@ -1,18 +1,18 @@
1
 <script>
1
 <script>
2
 import draggable from 'vuedraggable'
2
 import draggable from 'vuedraggable'
3
-import render from '@/utils/generator/render'
3
+import render from '@/components/render/render'
4
 
4
 
5
 const components = {
5
 const components = {
6
-  itemBtns(h, element, index, parent) {
6
+  itemBtns(h, currentItem, index, list) {
7
     const { copyItem, deleteItem } = this.$listeners
7
     const { copyItem, deleteItem } = this.$listeners
8
     return [
8
     return [
9
       <span class="drawing-item-copy" title="复制" onClick={event => {
9
       <span class="drawing-item-copy" title="复制" onClick={event => {
10
-        copyItem(element, parent); event.stopPropagation()
10
+        copyItem(currentItem, list); event.stopPropagation()
11
       }}>
11
       }}>
12
         <i class="el-icon-copy-document" />
12
         <i class="el-icon-copy-document" />
13
       </span>,
13
       </span>,
14
       <span class="drawing-item-delete" title="删除" onClick={event => {
14
       <span class="drawing-item-delete" title="删除" onClick={event => {
15
-        deleteItem(index, parent); event.stopPropagation()
15
+        deleteItem(index, list); event.stopPropagation()
16
       }}>
16
       }}>
17
         <i class="el-icon-delete" />
17
         <i class="el-icon-delete" />
18
       </span>
18
       </span>
@@ -20,60 +20,80 @@ const components = {
20
   }
20
   }
21
 }
21
 }
22
 const layouts = {
22
 const layouts = {
23
-  colFormItem(h, element, index, parent) {
23
+  colFormItem(h, currentItem, index, list) {
24
     const { activeItem } = this.$listeners
24
     const { activeItem } = this.$listeners
25
-    let className = this.activeId === element.formId ? 'drawing-item active-from-item' : 'drawing-item'
25
+    const config = currentItem.__config__
26
+    const child = renderChildren.apply(this, arguments)
27
+    let className = this.activeId === config.formId ? 'drawing-item active-from-item' : 'drawing-item'
26
     if (this.formConf.unFocusedComponentBorder) className += ' unfocus-bordered'
28
     if (this.formConf.unFocusedComponentBorder) className += ' unfocus-bordered'
29
+    let labelWidth = config.labelWidth ? `${config.labelWidth}px` : null
30
+    if (config.showLabel === false) labelWidth = '0'
27
     return (
31
     return (
28
-      <el-col span={element.span} class={className}
29
-        nativeOnClick={event => { activeItem(element); event.stopPropagation() }}>
30
-        <el-form-item label-width={element.labelWidth ? `${element.labelWidth}px` : null}
31
-          label={element.label} required={element.required}>
32
-          <render key={element.renderKey} conf={element} onInput={ event => {
33
-            this.$set(element, 'defaultValue', event)
34
-          }} />
32
+      <el-col span={config.span} class={className}
33
+              nativeOnClick={event => { activeItem(currentItem); event.stopPropagation() }}>
34
+        <el-form-item label-width={labelWidth}
35
+                      label={config.showLabel ? config.label : ''} required={config.required}>
36
+          <render key={config.renderKey} conf={currentItem} onInput={ event => {
37
+            this.$set(config, 'defaultValue', event)
38
+          }}>
39
+            {child}
40
+          </render>
35
         </el-form-item>
41
         </el-form-item>
36
         {components.itemBtns.apply(this, arguments)}
42
         {components.itemBtns.apply(this, arguments)}
37
       </el-col>
43
       </el-col>
38
     )
44
     )
39
   },
45
   },
40
-  rowFormItem(h, element, index, parent) {
46
+  rowFormItem(h, currentItem, index, list) {
41
     const { activeItem } = this.$listeners
47
     const { activeItem } = this.$listeners
42
-    const className = this.activeId === element.formId ? 'drawing-row-item active-from-item' : 'drawing-row-item'
48
+    const config = currentItem.__config__
49
+    const className = this.activeId === config.formId
50
+      ? 'drawing-row-item active-from-item'
51
+      : 'drawing-row-item'
43
     let child = renderChildren.apply(this, arguments)
52
     let child = renderChildren.apply(this, arguments)
44
-    if (element.type === 'flex') {
45
-      child = <el-row type={element.type} justify={element.justify} align={element.align}>
46
-              {child}
47
-            </el-row>
53
+    if (currentItem.type === 'flex') {
54
+      child = <el-row type={currentItem.type} justify={currentItem.justify} align={currentItem.align}>
55
+        {child}
56
+      </el-row>
48
     }
57
     }
49
     return (
58
     return (
50
-      <el-col span={element.span}>
51
-        <el-row gutter={element.gutter} class={className}
52
-          nativeOnClick={event => { activeItem(element); event.stopPropagation() }}>
53
-          <span class="component-name">{element.componentName}</span>
54
-          <draggable list={element.children} animation={340} group="componentsGroup" class="drag-wrapper">
59
+      <el-col span={config.span}>
60
+        <el-row gutter={config.gutter} class={className}
61
+                nativeOnClick={event => { activeItem(currentItem); event.stopPropagation() }}>
62
+          <span class="component-name">{config.componentName}</span>
63
+          <draggable list={config.children || []} animation={340}
64
+                     group="componentsGroup" class="drag-wrapper">
55
             {child}
65
             {child}
56
           </draggable>
66
           </draggable>
57
           {components.itemBtns.apply(this, arguments)}
67
           {components.itemBtns.apply(this, arguments)}
58
         </el-row>
68
         </el-row>
59
       </el-col>
69
       </el-col>
60
     )
70
     )
71
+  },
72
+  raw(h, currentItem, index, list) {
73
+    const config = currentItem.__config__
74
+    const child = renderChildren.apply(this, arguments)
75
+    return <render key={config.renderKey} conf={currentItem} onInput={ event => {
76
+      this.$set(config, 'defaultValue', event)
77
+    }}>
78
+      {child}
79
+    </render>
61
   }
80
   }
62
 }
81
 }
63
 
82
 
64
-function renderChildren(h, element, index, parent) {
65
-  if (!Array.isArray(element.children)) return null
66
-  return element.children.map((el, i) => {
67
-    const layout = layouts[el.layout]
83
+function renderChildren(h, currentItem, index, list) {
84
+  const config = currentItem.__config__
85
+  if (!Array.isArray(config.children)) return null
86
+  return config.children.map((el, i) => {
87
+    const layout = layouts[el.__config__.layout]
68
     if (layout) {
88
     if (layout) {
69
-      return layout.call(this, h, el, i, element.children)
89
+      return layout.call(this, h, el, i, config.children)
70
     }
90
     }
71
-    return layoutIsNotFound()
91
+    return layoutIsNotFound.call(this)
72
   })
92
   })
73
 }
93
 }
74
 
94
 
75
 function layoutIsNotFound() {
95
 function layoutIsNotFound() {
76
-  throw new Error(`没有与${this.element.layout}匹配的layout`)
96
+  throw new Error(`没有与${this.currentItem.__config__.layout}匹配的layout`)
77
 }
97
 }
78
 
98
 
79
 export default {
99
 export default {
@@ -82,19 +102,19 @@ export default {
82
     draggable
102
     draggable
83
   },
103
   },
84
   props: [
104
   props: [
85
-    'element',
105
+    'currentItem',
86
     'index',
106
     'index',
87
     'drawingList',
107
     'drawingList',
88
     'activeId',
108
     'activeId',
89
     'formConf'
109
     'formConf'
90
   ],
110
   ],
91
   render(h) {
111
   render(h) {
92
-    const layout = layouts[this.element.layout]
112
+    const layout = layouts[this.currentItem.__config__.layout]
93
 
113
 
94
     if (layout) {
114
     if (layout) {
95
-      return layout.call(this, h, this.element, this.index, this.drawingList)
115
+      return layout.call(this, h, this.currentItem, this.index, this.drawingList)
96
     }
116
     }
97
-    return layoutIsNotFound()
117
+    return layoutIsNotFound.call(this)
98
   }
118
   }
99
 }
119
 }
100
 </script>
120
 </script>

+ 222 - 116
src/views/tool/build/RightPanel.vue

@@ -11,9 +11,9 @@
11
       <el-scrollbar class="right-scrollbar">
11
       <el-scrollbar class="right-scrollbar">
12
         <!-- 组件属性 -->
12
         <!-- 组件属性 -->
13
         <el-form v-show="currentTab==='field' && showField" size="small" label-width="90px">
13
         <el-form v-show="currentTab==='field' && showField" size="small" label-width="90px">
14
-          <el-form-item v-if="activeData.changeTag" label="组件类型">
14
+          <el-form-item v-if="activeData.__config__.changeTag" label="组件类型">
15
             <el-select
15
             <el-select
16
-              v-model="activeData.tagIcon"
16
+              v-model="activeData.__config__.tagIcon"
17
               placeholder="请选择组件类型"
17
               placeholder="请选择组件类型"
18
               :style="{width: '100%'}"
18
               :style="{width: '100%'}"
19
               @change="tagChange"
19
               @change="tagChange"
@@ -21,27 +21,27 @@
21
               <el-option-group v-for="group in tagList" :key="group.label" :label="group.label">
21
               <el-option-group v-for="group in tagList" :key="group.label" :label="group.label">
22
                 <el-option
22
                 <el-option
23
                   v-for="item in group.options"
23
                   v-for="item in group.options"
24
-                  :key="item.label"
25
-                  :label="item.label"
26
-                  :value="item.tagIcon"
24
+                  :key="item.__config__.label"
25
+                  :label="item.__config__.label"
26
+                  :value="item.__config__.tagIcon"
27
                 >
27
                 >
28
-                  <svg-icon class="node-icon" :icon-class="item.tagIcon" />
29
-                  <span> {{ item.label }}</span>
28
+                  <svg-icon class="node-icon" :icon-class="item.__config__.tagIcon" />
29
+                  <span> {{ item.__config__.label }}</span>
30
                 </el-option>
30
                 </el-option>
31
               </el-option-group>
31
               </el-option-group>
32
             </el-select>
32
             </el-select>
33
           </el-form-item>
33
           </el-form-item>
34
-          <el-form-item v-if="activeData.vModel!==undefined" label="字段名">
35
-            <el-input v-model="activeData.vModel" placeholder="请输入字段名(v-model)" />
34
+          <el-form-item v-if="activeData.__vModel__!==undefined" label="字段名">
35
+            <el-input v-model="activeData.__vModel__" placeholder="请输入字段名(v-model)" />
36
           </el-form-item>
36
           </el-form-item>
37
-          <el-form-item v-if="activeData.componentName!==undefined" label="组件名">
38
-            {{ activeData.componentName }}
37
+          <el-form-item v-if="activeData.__config__.componentName!==undefined" label="组件名">
38
+            {{ activeData.__config__.componentName }}
39
           </el-form-item>
39
           </el-form-item>
40
-          <el-form-item v-if="activeData.label!==undefined" label="标题">
41
-            <el-input v-model="activeData.label" placeholder="请输入标题" />
40
+          <el-form-item v-if="activeData.__config__.label!==undefined" label="标题">
41
+            <el-input v-model="activeData.__config__.label" placeholder="请输入标题" @input="changeRenderKey" />
42
           </el-form-item>
42
           </el-form-item>
43
           <el-form-item v-if="activeData.placeholder!==undefined" label="占位提示">
43
           <el-form-item v-if="activeData.placeholder!==undefined" label="占位提示">
44
-            <el-input v-model="activeData.placeholder" placeholder="请输入占位提示" />
44
+            <el-input v-model="activeData.placeholder" placeholder="请输入占位提示" @input="changeRenderKey" />
45
           </el-form-item>
45
           </el-form-item>
46
           <el-form-item v-if="activeData['start-placeholder']!==undefined" label="开始占位">
46
           <el-form-item v-if="activeData['start-placeholder']!==undefined" label="开始占位">
47
             <el-input v-model="activeData['start-placeholder']" placeholder="请输入占位提示" />
47
             <el-input v-model="activeData['start-placeholder']" placeholder="请输入占位提示" />
@@ -49,13 +49,13 @@
49
           <el-form-item v-if="activeData['end-placeholder']!==undefined" label="结束占位">
49
           <el-form-item v-if="activeData['end-placeholder']!==undefined" label="结束占位">
50
             <el-input v-model="activeData['end-placeholder']" placeholder="请输入占位提示" />
50
             <el-input v-model="activeData['end-placeholder']" placeholder="请输入占位提示" />
51
           </el-form-item>
51
           </el-form-item>
52
-          <el-form-item v-if="activeData.span!==undefined" label="表单栅格">
53
-            <el-slider v-model="activeData.span" :max="24" :min="1" :marks="{12:''}" @change="spanChange" />
52
+          <el-form-item v-if="activeData.__config__.span!==undefined" label="表单栅格">
53
+            <el-slider v-model="activeData.__config__.span" :max="24" :min="1" :marks="{12:''}" @change="spanChange" />
54
           </el-form-item>
54
           </el-form-item>
55
-          <el-form-item v-if="activeData.layout==='rowFormItem'" label="栅格间隔">
55
+          <el-form-item v-if="activeData.__config__.layout==='rowFormItem'&&activeData.gutter!==undefined" label="栅格间隔">
56
             <el-input-number v-model="activeData.gutter" :min="0" placeholder="栅格间隔" />
56
             <el-input-number v-model="activeData.gutter" :min="0" placeholder="栅格间隔" />
57
           </el-form-item>
57
           </el-form-item>
58
-          <el-form-item v-if="activeData.layout==='rowFormItem'" label="布局模式">
58
+          <el-form-item v-if="activeData.__config__.layout==='rowFormItem'&&activeData.type!==undefined" label="布局模式">
59
             <el-radio-group v-model="activeData.type">
59
             <el-radio-group v-model="activeData.type">
60
               <el-radio-button label="default" />
60
               <el-radio-button label="default" />
61
               <el-radio-button label="flex" />
61
               <el-radio-button label="flex" />
@@ -78,20 +78,20 @@
78
               <el-radio-button label="bottom" />
78
               <el-radio-button label="bottom" />
79
             </el-radio-group>
79
             </el-radio-group>
80
           </el-form-item>
80
           </el-form-item>
81
-          <el-form-item v-if="activeData.labelWidth!==undefined" label="标签宽度">
82
-            <el-input v-model.number="activeData.labelWidth" type="number" placeholder="请输入标签宽度" />
81
+          <el-form-item v-if="activeData.__config__.labelWidth!==undefined" label="标签宽度">
82
+            <el-input v-model.number="activeData.__config__.labelWidth" type="number" placeholder="请输入标签宽度" />
83
           </el-form-item>
83
           </el-form-item>
84
           <el-form-item v-if="activeData.style&&activeData.style.width!==undefined" label="组件宽度">
84
           <el-form-item v-if="activeData.style&&activeData.style.width!==undefined" label="组件宽度">
85
             <el-input v-model="activeData.style.width" placeholder="请输入组件宽度" clearable />
85
             <el-input v-model="activeData.style.width" placeholder="请输入组件宽度" clearable />
86
           </el-form-item>
86
           </el-form-item>
87
-          <el-form-item v-if="activeData.vModel!==undefined" label="默认值">
87
+          <el-form-item v-if="activeData.__vModel__!==undefined" label="默认值">
88
             <el-input
88
             <el-input
89
-              :value="setDefaultValue(activeData.defaultValue)"
89
+              :value="setDefaultValue(activeData.__config__.defaultValue)"
90
               placeholder="请输入默认值"
90
               placeholder="请输入默认值"
91
               @input="onDefaultValueInput"
91
               @input="onDefaultValueInput"
92
             />
92
             />
93
           </el-form-item>
93
           </el-form-item>
94
-          <el-form-item v-if="activeData.tag==='el-checkbox-group'" label="至少应选">
94
+          <el-form-item v-if="activeData.__config__.tag==='el-checkbox-group'" label="至少应选">
95
             <el-input-number
95
             <el-input-number
96
               :value="activeData.min"
96
               :value="activeData.min"
97
               :min="0"
97
               :min="0"
@@ -99,7 +99,7 @@
99
               @input="$set(activeData, 'min', $event?$event:undefined)"
99
               @input="$set(activeData, 'min', $event?$event:undefined)"
100
             />
100
             />
101
           </el-form-item>
101
           </el-form-item>
102
-          <el-form-item v-if="activeData.tag==='el-checkbox-group'" label="最多可选">
102
+          <el-form-item v-if="activeData.__config__.tag==='el-checkbox-group'" label="最多可选">
103
             <el-input-number
103
             <el-input-number
104
               :value="activeData.max"
104
               :value="activeData.max"
105
               :min="0"
105
               :min="0"
@@ -107,11 +107,11 @@
107
               @input="$set(activeData, 'max', $event?$event:undefined)"
107
               @input="$set(activeData, 'max', $event?$event:undefined)"
108
             />
108
             />
109
           </el-form-item>
109
           </el-form-item>
110
-          <el-form-item v-if="activeData.prepend!==undefined" label="前缀">
111
-            <el-input v-model="activeData.prepend" placeholder="请输入前缀" />
110
+          <el-form-item v-if="activeData.__slot__&&activeData.__slot__.prepend!==undefined" label="前缀">
111
+            <el-input v-model="activeData.__slot__.prepend" placeholder="请输入前缀" />
112
           </el-form-item>
112
           </el-form-item>
113
-          <el-form-item v-if="activeData.append!==undefined" label="后缀">
114
-            <el-input v-model="activeData.append" placeholder="请输入后缀" />
113
+          <el-form-item v-if="activeData.__slot__&&activeData.__slot__.append!==undefined" label="后缀">
114
+            <el-input v-model="activeData.__slot__.append" placeholder="请输入后缀" />
115
           </el-form-item>
115
           </el-form-item>
116
           <el-form-item v-if="activeData['prefix-icon']!==undefined" label="前图标">
116
           <el-form-item v-if="activeData['prefix-icon']!==undefined" label="前图标">
117
             <el-input v-model="activeData['prefix-icon']" placeholder="请输入前图标名称">
117
             <el-input v-model="activeData['prefix-icon']" placeholder="请输入前图标名称">
@@ -127,7 +127,17 @@
127
               </el-button>
127
               </el-button>
128
             </el-input>
128
             </el-input>
129
           </el-form-item>
129
           </el-form-item>
130
-          <el-form-item v-if="activeData.tag === 'el-cascader'" label="选项分隔符">
130
+          <el-form-item
131
+            v-if="activeData['icon']!==undefined && activeData.__config__.tag === 'el-button'"
132
+            label="按钮图标"
133
+          >
134
+            <el-input v-model="activeData['icon']" placeholder="请输入按钮图标名称">
135
+              <el-button slot="append" icon="el-icon-thumb" @click="openIconsDialog('icon')">
136
+                选择
137
+              </el-button>
138
+            </el-input>
139
+          </el-form-item>
140
+          <el-form-item v-if="activeData.__config__.tag === 'el-cascader'" label="选项分隔符">
131
             <el-input v-model="activeData.separator" placeholder="请输入选项分隔符" />
141
             <el-input v-model="activeData.separator" placeholder="请输入选项分隔符" />
132
           </el-form-item>
142
           </el-form-item>
133
           <el-form-item v-if="activeData.autosize !== undefined" label="最小行数">
143
           <el-form-item v-if="activeData.autosize !== undefined" label="最小行数">
@@ -136,19 +146,22 @@
136
           <el-form-item v-if="activeData.autosize !== undefined" label="最大行数">
146
           <el-form-item v-if="activeData.autosize !== undefined" label="最大行数">
137
             <el-input-number v-model="activeData.autosize.maxRows" :min="1" placeholder="最大行数" />
147
             <el-input-number v-model="activeData.autosize.maxRows" :min="1" placeholder="最大行数" />
138
           </el-form-item>
148
           </el-form-item>
139
-          <el-form-item v-if="activeData.min !== undefined" label="最小值">
149
+          <el-form-item v-if="isShowMin" label="最小值">
140
             <el-input-number v-model="activeData.min" placeholder="最小值" />
150
             <el-input-number v-model="activeData.min" placeholder="最小值" />
141
           </el-form-item>
151
           </el-form-item>
142
-          <el-form-item v-if="activeData.max !== undefined" label="最大值">
152
+          <el-form-item v-if="isShowMax" label="最大值">
143
             <el-input-number v-model="activeData.max" placeholder="最大值" />
153
             <el-input-number v-model="activeData.max" placeholder="最大值" />
144
           </el-form-item>
154
           </el-form-item>
145
-          <el-form-item v-if="activeData.step !== undefined" label="步长">
155
+          <el-form-item v-if="activeData.height!==undefined" label="组件高度">
156
+            <el-input-number v-model="activeData.height" placeholder="高度" @input="changeRenderKey" />
157
+          </el-form-item>
158
+          <el-form-item v-if="isShowStep" label="步长">
146
             <el-input-number v-model="activeData.step" placeholder="步数" />
159
             <el-input-number v-model="activeData.step" placeholder="步数" />
147
           </el-form-item>
160
           </el-form-item>
148
-          <el-form-item v-if="activeData.tag === 'el-input-number'" label="精度">
161
+          <el-form-item v-if="activeData.__config__.tag === 'el-input-number'" label="精度">
149
             <el-input-number v-model="activeData.precision" :min="0" placeholder="精度" />
162
             <el-input-number v-model="activeData.precision" :min="0" placeholder="精度" />
150
           </el-form-item>
163
           </el-form-item>
151
-          <el-form-item v-if="activeData.tag === 'el-input-number'" label="按钮位置">
164
+          <el-form-item v-if="activeData.__config__.tag === 'el-input-number'" label="按钮位置">
152
             <el-radio-group v-model="activeData['controls-position']">
165
             <el-radio-group v-model="activeData['controls-position']">
153
               <el-radio-button label="">
166
               <el-radio-button label="">
154
                 默认
167
                 默认
@@ -186,7 +199,7 @@
186
             />
199
             />
187
           </el-form-item>
200
           </el-form-item>
188
           <el-form-item
201
           <el-form-item
189
-            v-if="activeData.type !== undefined && 'el-date-picker' === activeData.tag"
202
+            v-if="activeData.type !== undefined && 'el-date-picker' === activeData.__config__.tag"
190
             label="时间类型"
203
             label="时间类型"
191
           >
204
           >
192
             <el-select
205
             <el-select
@@ -222,9 +235,9 @@
222
               <el-option label="txt" value=".txt" />
235
               <el-option label="txt" value=".txt" />
223
             </el-select>
236
             </el-select>
224
           </el-form-item>
237
           </el-form-item>
225
-          <el-form-item v-if="activeData.fileSize !== undefined" label="文件大小">
226
-            <el-input v-model.number="activeData.fileSize" placeholder="请输入文件大小">
227
-              <el-select slot="append" v-model="activeData.sizeUnit" :style="{ width: '66px' }">
238
+          <el-form-item v-if="activeData.__config__.fileSize !== undefined" label="文件大小">
239
+            <el-input v-model.number="activeData.__config__.fileSize" placeholder="请输入文件大小">
240
+              <el-select slot="append" v-model="activeData.__config__.sizeUnit" :style="{ width: '66px' }">
228
                 <el-option label="KB" value="KB" />
241
                 <el-option label="KB" value="KB" />
229
                 <el-option label="MB" value="MB" />
242
                 <el-option label="MB" value="MB" />
230
                 <el-option label="GB" value="GB" />
243
                 <el-option label="GB" value="GB" />
@@ -248,11 +261,30 @@
248
             </el-radio-group>
261
             </el-radio-group>
249
           </el-form-item>
262
           </el-form-item>
250
           <el-form-item
263
           <el-form-item
251
-            v-if="activeData.buttonText !== undefined"
264
+            v-if="activeData.type !== undefined && activeData.__config__.tag === 'el-button'"
265
+            label="按钮类型"
266
+          >
267
+            <el-select v-model="activeData.type" :style="{ width: '100%' }">
268
+              <el-option label="primary" value="primary" />
269
+              <el-option label="success" value="success" />
270
+              <el-option label="warning" value="warning" />
271
+              <el-option label="danger" value="danger" />
272
+              <el-option label="info" value="info" />
273
+              <el-option label="text" value="text" />
274
+            </el-select>
275
+          </el-form-item>
276
+          <el-form-item
277
+            v-if="activeData.__config__.buttonText !== undefined"
252
             v-show="'picture-card' !== activeData['list-type']"
278
             v-show="'picture-card' !== activeData['list-type']"
253
             label="按钮文字"
279
             label="按钮文字"
254
           >
280
           >
255
-            <el-input v-model="activeData.buttonText" placeholder="请输入按钮文字" />
281
+            <el-input v-model="activeData.__config__.buttonText" placeholder="请输入按钮文字" />
282
+          </el-form-item>
283
+          <el-form-item
284
+            v-if="activeData.__config__.tag === 'el-button'"
285
+            label="按钮文字"
286
+          >
287
+            <el-input v-model="activeData.__slot__.default" placeholder="请输入按钮文字" />
256
           </el-form-item>
288
           </el-form-item>
257
           <el-form-item v-if="activeData['range-separator'] !== undefined" label="分隔符">
289
           <el-form-item v-if="activeData['range-separator'] !== undefined" label="分隔符">
258
             <el-input v-model="activeData['range-separator']" placeholder="请输入分隔符" />
290
             <el-input v-model="activeData['range-separator']" placeholder="请输入分隔符" />
@@ -270,15 +302,15 @@
270
               @input="setTimeValue($event)"
302
               @input="setTimeValue($event)"
271
             />
303
             />
272
           </el-form-item>
304
           </el-form-item>
273
-          <template v-if="['el-checkbox-group', 'el-radio-group', 'el-select'].indexOf(activeData.tag) > -1">
305
+          <template v-if="['el-checkbox-group', 'el-radio-group', 'el-select'].indexOf(activeData.__config__.tag) > -1">
274
             <el-divider>选项</el-divider>
306
             <el-divider>选项</el-divider>
275
             <draggable
307
             <draggable
276
-              :list="activeData.options"
308
+              :list="activeData.__slot__.options"
277
               :animation="340"
309
               :animation="340"
278
               group="selectItem"
310
               group="selectItem"
279
               handle=".option-drag"
311
               handle=".option-drag"
280
             >
312
             >
281
-              <div v-for="(item, index) in activeData.options" :key="index" class="select-item">
313
+              <div v-for="(item, index) in activeData.__slot__.options" :key="index" class="select-item">
282
                 <div class="select-line-icon option-drag">
314
                 <div class="select-line-icon option-drag">
283
                   <i class="el-icon-s-operation" />
315
                   <i class="el-icon-s-operation" />
284
                 </div>
316
                 </div>
@@ -289,7 +321,7 @@
289
                   :value="item.value"
321
                   :value="item.value"
290
                   @input="setOptionValue(item, $event)"
322
                   @input="setOptionValue(item, $event)"
291
                 />
323
                 />
292
-                <div class="close-btn select-line-icon" @click="activeData.options.splice(index, 1)">
324
+                <div class="close-btn select-line-icon" @click="activeData.__slot__.options.splice(index, 1)">
293
                   <i class="el-icon-remove-outline" />
325
                   <i class="el-icon-remove-outline" />
294
                 </div>
326
                 </div>
295
               </div>
327
               </div>
@@ -307,10 +339,10 @@
307
             <el-divider />
339
             <el-divider />
308
           </template>
340
           </template>
309
 
341
 
310
-          <template v-if="['el-cascader'].indexOf(activeData.tag) > -1">
342
+          <template v-if="['el-cascader', 'el-table'].includes(activeData.__config__.tag)">
311
             <el-divider>选项</el-divider>
343
             <el-divider>选项</el-divider>
312
-            <el-form-item label="数据类型">
313
-              <el-radio-group v-model="activeData.dataType" size="small">
344
+            <el-form-item v-if="activeData.__config__.dataType" label="数据类型">
345
+              <el-radio-group v-model="activeData.__config__.dataType" size="small">
314
                 <el-radio-button label="dynamic">
346
                 <el-radio-button label="dynamic">
315
                   动态数据
347
                   动态数据
316
                 </el-radio-button>
348
                 </el-radio-button>
@@ -320,27 +352,59 @@
320
               </el-radio-group>
352
               </el-radio-group>
321
             </el-form-item>
353
             </el-form-item>
322
 
354
 
323
-            <template v-if="activeData.dataType === 'dynamic'">
324
-              <el-form-item label="标签键名">
325
-                <el-input v-model="activeData.labelKey" placeholder="请输入标签键名" />
326
-              </el-form-item>
327
-              <el-form-item label="值键名">
328
-                <el-input v-model="activeData.valueKey" placeholder="请输入值键名" />
355
+            <template v-if="activeData.__config__.dataType === 'dynamic'">
356
+              <el-form-item label="接口地址">
357
+                <el-input
358
+                  v-model="activeData.__config__.url"
359
+                  :title="activeData.__config__.url"
360
+                  placeholder="请输入接口地址"
361
+                  clearable
362
+                  @blur="$emit('fetch-data', activeData)"
363
+                >
364
+                  <el-select
365
+                    slot="prepend"
366
+                    v-model="activeData.__config__.method"
367
+                    :style="{width: '85px'}"
368
+                    @change="$emit('fetch-data', activeData)"
369
+                  >
370
+                    <el-option label="get" value="get" />
371
+                    <el-option label="post" value="post" />
372
+                    <el-option label="put" value="put" />
373
+                    <el-option label="delete" value="delete" />
374
+                  </el-select>
375
+                </el-input>
329
               </el-form-item>
376
               </el-form-item>
330
-              <el-form-item label="子级键名">
331
-                <el-input v-model="activeData.childrenKey" placeholder="请输入子级键名" />
377
+              <el-form-item label="数据位置">
378
+                <el-input
379
+                  v-model="activeData.__config__.dataPath"
380
+                  placeholder="请输入数据位置"
381
+                  @blur="$emit('fetch-data', activeData)"
382
+                />
332
               </el-form-item>
383
               </el-form-item>
384
+
385
+              <template v-if="activeData.props && activeData.props.props">
386
+                <el-form-item label="标签键名">
387
+                  <el-input v-model="activeData.props.props.label" placeholder="请输入标签键名" />
388
+                </el-form-item>
389
+                <el-form-item label="值键名">
390
+                  <el-input v-model="activeData.props.props.value" placeholder="请输入值键名" />
391
+                </el-form-item>
392
+                <el-form-item label="子级键名">
393
+                  <el-input v-model="activeData.props.props.children" placeholder="请输入子级键名" />
394
+                </el-form-item>
395
+              </template>
333
             </template>
396
             </template>
334
 
397
 
398
+            <!-- 级联选择静态树 -->
335
             <el-tree
399
             <el-tree
336
-              v-if="activeData.dataType === 'static'"
400
+              v-if="activeData.__config__.dataType === 'static'"
337
               draggable
401
               draggable
338
               :data="activeData.options"
402
               :data="activeData.options"
339
               node-key="id"
403
               node-key="id"
340
               :expand-on-click-node="false"
404
               :expand-on-click-node="false"
341
               :render-content="renderContent"
405
               :render-content="renderContent"
342
             />
406
             />
343
-            <div v-if="activeData.dataType === 'static'" style="margin-left: 20px">
407
+            <div v-if="activeData.__config__.dataType === 'static'" style="margin-left: 20px">
344
               <el-button
408
               <el-button
345
                 style="padding-bottom: 0"
409
                 style="padding-bottom: 0"
346
                 icon="el-icon-circle-plus-outline"
410
                 icon="el-icon-circle-plus-outline"
@@ -353,8 +417,8 @@
353
             <el-divider />
417
             <el-divider />
354
           </template>
418
           </template>
355
 
419
 
356
-          <el-form-item v-if="activeData.optionType !== undefined" label="选项样式">
357
-            <el-radio-group v-model="activeData.optionType">
420
+          <el-form-item v-if="activeData.__config__.optionType !== undefined" label="选项样式">
421
+            <el-radio-group v-model="activeData.__config__.optionType">
358
               <el-radio-button label="default">
422
               <el-radio-button label="default">
359
                 默认
423
                 默认
360
               </el-radio-button>
424
               </el-radio-button>
@@ -370,6 +434,14 @@
370
             <el-color-picker v-model="activeData['inactive-color']" />
434
             <el-color-picker v-model="activeData['inactive-color']" />
371
           </el-form-item>
435
           </el-form-item>
372
 
436
 
437
+          <el-form-item v-if="activeData.__config__.showLabel !== undefined
438
+            && activeData.__config__.labelWidth !== undefined" label="显示标签"
439
+          >
440
+            <el-switch v-model="activeData.__config__.showLabel" />
441
+          </el-form-item>
442
+          <el-form-item v-if="activeData.branding !== undefined" label="品牌烙印">
443
+            <el-switch v-model="activeData.branding" @input="changeRenderKey" />
444
+          </el-form-item>
373
           <el-form-item v-if="activeData['allow-half'] !== undefined" label="允许半选">
445
           <el-form-item v-if="activeData['allow-half'] !== undefined" label="允许半选">
374
             <el-switch v-model="activeData['allow-half']" />
446
             <el-switch v-model="activeData['allow-half']" />
375
           </el-form-item>
447
           </el-form-item>
@@ -386,16 +458,17 @@
386
             <el-switch v-model="activeData.range" @change="rangeChange" />
458
             <el-switch v-model="activeData.range" @change="rangeChange" />
387
           </el-form-item>
459
           </el-form-item>
388
           <el-form-item
460
           <el-form-item
389
-            v-if="activeData.border !== undefined && activeData.optionType === 'default'"
461
+            v-if="activeData.__config__.border !== undefined && activeData.__config__.optionType === 'default'"
390
             label="是否带边框"
462
             label="是否带边框"
391
           >
463
           >
392
-            <el-switch v-model="activeData.border" />
464
+            <el-switch v-model="activeData.__config__.border" />
393
           </el-form-item>
465
           </el-form-item>
394
-          <el-form-item v-if="activeData.tag === 'el-color-picker'" label="颜色格式">
466
+          <el-form-item v-if="activeData.__config__.tag === 'el-color-picker'" label="颜色格式">
395
             <el-select
467
             <el-select
396
               v-model="activeData['color-format']"
468
               v-model="activeData['color-format']"
397
               placeholder="请选择颜色格式"
469
               placeholder="请选择颜色格式"
398
               :style="{ width: '100%' }"
470
               :style="{ width: '100%' }"
471
+              clearable
399
               @change="colorFormatChange"
472
               @change="colorFormatChange"
400
             >
473
             >
401
               <el-option
474
               <el-option
@@ -408,10 +481,11 @@
408
           </el-form-item>
481
           </el-form-item>
409
           <el-form-item
482
           <el-form-item
410
             v-if="activeData.size !== undefined &&
483
             v-if="activeData.size !== undefined &&
411
-              (activeData.optionType === 'button' ||
412
-                activeData.border ||
413
-                activeData.tag === 'el-color-picker')"
414
-            label="选项尺寸"
484
+              (activeData.__config__.optionType === 'button' ||
485
+                activeData.__config__.border ||
486
+                activeData.__config__.tag === 'el-color-picker' ||
487
+                activeData.__config__.tag === 'el-button')"
488
+            label="组件尺寸"
415
           >
489
           >
416
             <el-radio-group v-model="activeData.size">
490
             <el-radio-group v-model="activeData.size">
417
               <el-radio-button label="medium">
491
               <el-radio-button label="medium">
@@ -428,25 +502,28 @@
428
           <el-form-item v-if="activeData['show-word-limit'] !== undefined" label="输入统计">
502
           <el-form-item v-if="activeData['show-word-limit'] !== undefined" label="输入统计">
429
             <el-switch v-model="activeData['show-word-limit']" />
503
             <el-switch v-model="activeData['show-word-limit']" />
430
           </el-form-item>
504
           </el-form-item>
431
-          <el-form-item v-if="activeData.tag === 'el-input-number'" label="严格步数">
505
+          <el-form-item v-if="activeData.__config__.tag === 'el-input-number'" label="严格步数">
432
             <el-switch v-model="activeData['step-strictly']" />
506
             <el-switch v-model="activeData['step-strictly']" />
433
           </el-form-item>
507
           </el-form-item>
434
-          <el-form-item v-if="activeData.tag === 'el-cascader'" label="是否多选">
508
+          <el-form-item v-if="activeData.__config__.tag === 'el-cascader'" label="任选层级">
509
+            <el-switch v-model="activeData.props.props.checkStrictly" />
510
+          </el-form-item>
511
+          <el-form-item v-if="activeData.__config__.tag === 'el-cascader'" label="是否多选">
435
             <el-switch v-model="activeData.props.props.multiple" />
512
             <el-switch v-model="activeData.props.props.multiple" />
436
           </el-form-item>
513
           </el-form-item>
437
-          <el-form-item v-if="activeData.tag === 'el-cascader'" label="展示全路径">
514
+          <el-form-item v-if="activeData.__config__.tag === 'el-cascader'" label="展示全路径">
438
             <el-switch v-model="activeData['show-all-levels']" />
515
             <el-switch v-model="activeData['show-all-levels']" />
439
           </el-form-item>
516
           </el-form-item>
440
-          <el-form-item v-if="activeData.tag === 'el-cascader'" label="可否筛选">
517
+          <el-form-item v-if="activeData.__config__.tag === 'el-cascader'" label="可否筛选">
441
             <el-switch v-model="activeData.filterable" />
518
             <el-switch v-model="activeData.filterable" />
442
           </el-form-item>
519
           </el-form-item>
443
           <el-form-item v-if="activeData.clearable !== undefined" label="能否清空">
520
           <el-form-item v-if="activeData.clearable !== undefined" label="能否清空">
444
             <el-switch v-model="activeData.clearable" />
521
             <el-switch v-model="activeData.clearable" />
445
           </el-form-item>
522
           </el-form-item>
446
-          <el-form-item v-if="activeData.showTip !== undefined" label="显示提示">
447
-            <el-switch v-model="activeData.showTip" />
523
+          <el-form-item v-if="activeData.__config__.showTip !== undefined" label="显示提示">
524
+            <el-switch v-model="activeData.__config__.showTip" />
448
           </el-form-item>
525
           </el-form-item>
449
-          <el-form-item v-if="activeData.multiple !== undefined" label="多选文件">
526
+          <el-form-item v-if="activeData.__config__.tag === 'el-upload'" label="多选文件">
450
             <el-switch v-model="activeData.multiple" />
527
             <el-switch v-model="activeData.multiple" />
451
           </el-form-item>
528
           </el-form-item>
452
           <el-form-item v-if="activeData['auto-upload'] !== undefined" label="自动上传">
529
           <el-form-item v-if="activeData['auto-upload'] !== undefined" label="自动上传">
@@ -458,20 +535,20 @@
458
           <el-form-item v-if="activeData.disabled !== undefined" label="是否禁用">
535
           <el-form-item v-if="activeData.disabled !== undefined" label="是否禁用">
459
             <el-switch v-model="activeData.disabled" />
536
             <el-switch v-model="activeData.disabled" />
460
           </el-form-item>
537
           </el-form-item>
461
-          <el-form-item v-if="activeData.tag === 'el-select'" label="是否可搜索">
538
+          <el-form-item v-if="activeData.__config__.tag === 'el-select'" label="能否搜索">
462
             <el-switch v-model="activeData.filterable" />
539
             <el-switch v-model="activeData.filterable" />
463
           </el-form-item>
540
           </el-form-item>
464
-          <el-form-item v-if="activeData.tag === 'el-select'" label="是否多选">
541
+          <el-form-item v-if="activeData.__config__.tag === 'el-select'" label="是否多选">
465
             <el-switch v-model="activeData.multiple" @change="multipleChange" />
542
             <el-switch v-model="activeData.multiple" @change="multipleChange" />
466
           </el-form-item>
543
           </el-form-item>
467
-          <el-form-item v-if="activeData.required !== undefined" label="是否必填">
468
-            <el-switch v-model="activeData.required" />
544
+          <el-form-item v-if="activeData.__config__.required !== undefined" label="是否必填">
545
+            <el-switch v-model="activeData.__config__.required" />
469
           </el-form-item>
546
           </el-form-item>
470
 
547
 
471
-          <template v-if="activeData.layoutTree">
548
+          <template v-if="activeData.__config__.layoutTree">
472
             <el-divider>布局结构树</el-divider>
549
             <el-divider>布局结构树</el-divider>
473
             <el-tree
550
             <el-tree
474
-              :data="[activeData]"
551
+              :data="[activeData.__config__]"
475
               :props="layoutTreeProps"
552
               :props="layoutTreeProps"
476
               node-key="renderKey"
553
               node-key="renderKey"
477
               default-expand-all
554
               default-expand-all
@@ -479,21 +556,21 @@
479
             >
556
             >
480
               <span slot-scope="{ node, data }">
557
               <span slot-scope="{ node, data }">
481
                 <span class="node-label">
558
                 <span class="node-label">
482
-                  <svg-icon class="node-icon" :icon-class="data.tagIcon" />
559
+                  <svg-icon class="node-icon" :icon-class="data.__config__?data.__config__.tagIcon:data.tagIcon" />
483
                   {{ node.label }}
560
                   {{ node.label }}
484
                 </span>
561
                 </span>
485
               </span>
562
               </span>
486
             </el-tree>
563
             </el-tree>
487
           </template>
564
           </template>
488
 
565
 
489
-          <template v-if="activeData.layout === 'colFormItem' && activeData.tag !== 'el-button'">
566
+          <template v-if="Array.isArray(activeData.__config__.regList)">
490
             <el-divider>正则校验</el-divider>
567
             <el-divider>正则校验</el-divider>
491
             <div
568
             <div
492
-              v-for="(item, index) in activeData.regList"
569
+              v-for="(item, index) in activeData.__config__.regList"
493
               :key="index"
570
               :key="index"
494
               class="reg-item"
571
               class="reg-item"
495
             >
572
             >
496
-              <span class="close-btn" @click="activeData.regList.splice(index, 1)">
573
+              <span class="close-btn" @click="activeData.__config__.regList.splice(index, 1)">
497
                 <i class="el-icon-close" />
574
                 <i class="el-icon-close" />
498
               </span>
575
               </span>
499
               <el-form-item label="表达式">
576
               <el-form-item label="表达式">
@@ -548,7 +625,7 @@
548
             </el-radio-group>
625
             </el-radio-group>
549
           </el-form-item>
626
           </el-form-item>
550
           <el-form-item label="标签宽度">
627
           <el-form-item label="标签宽度">
551
-            <el-input-number v-model="formConf.labelWidth" placeholder="标签宽度" />
628
+            <el-input v-model.number="formConf.labelWidth" type="number" placeholder="请输入标签宽度" />
552
           </el-form-item>
629
           </el-form-item>
553
           <el-form-item label="栅格间隔">
630
           <el-form-item label="栅格间隔">
554
             <el-input-number v-model="formConf.gutter" :min="0" placeholder="栅格间隔" />
631
             <el-input-number v-model="formConf.gutter" :min="0" placeholder="栅格间隔" />
@@ -572,16 +649,15 @@
572
 </template>
649
 </template>
573
 
650
 
574
 <script>
651
 <script>
575
-import { isArray } from 'util'
576
 import draggable from 'vuedraggable'
652
 import draggable from 'vuedraggable'
653
+import { isArray } from 'util'
577
 import TreeNodeDialog from './TreeNodeDialog'
654
 import TreeNodeDialog from './TreeNodeDialog'
578
-import { isNumberStr } from '@/utils/index'
655
+import { isNumberStr } from '@/utils'
579
 import IconsDialog from './IconsDialog'
656
 import IconsDialog from './IconsDialog'
580
 import {
657
 import {
581
-  inputComponents,
582
-  selectComponents,
583
-  layoutComponents
658
+  inputComponents, selectComponents, layoutComponents
584
 } from '@/utils/generator/config'
659
 } from '@/utils/generator/config'
660
+import { saveFormConf } from '@/utils/db'
585
 
661
 
586
 const dateTimeFormat = {
662
 const dateTimeFormat = {
587
   date: 'yyyy-MM-dd',
663
   date: 'yyyy-MM-dd',
@@ -594,11 +670,14 @@ const dateTimeFormat = {
594
   datetimerange: 'yyyy-MM-dd HH:mm:ss'
670
   datetimerange: 'yyyy-MM-dd HH:mm:ss'
595
 }
671
 }
596
 
672
 
673
+// 使changeRenderKey在目标组件改变时可用
674
+const needRerenderList = ['tinymce']
675
+
597
 export default {
676
 export default {
598
   components: {
677
   components: {
599
-    draggable,
600
     TreeNodeDialog,
678
     TreeNodeDialog,
601
-    IconsDialog
679
+    IconsDialog,
680
+    draggable
602
   },
681
   },
603
   props: ['showField', 'activeData', 'formConf'],
682
   props: ['showField', 'activeData', 'formConf'],
604
   data() {
683
   data() {
@@ -690,7 +769,8 @@ export default {
690
       ],
769
       ],
691
       layoutTreeProps: {
770
       layoutTreeProps: {
692
         label(data, node) {
771
         label(data, node) {
693
-          return data.componentName || `${data.label}: ${data.vModel}`
772
+          const config = data.__config__
773
+          return data.componentName || `${config.label}: ${data.__vModel__}`
694
         }
774
         }
695
       }
775
       }
696
     }
776
     }
@@ -698,14 +778,14 @@ export default {
698
   computed: {
778
   computed: {
699
     documentLink() {
779
     documentLink() {
700
       return (
780
       return (
701
-        this.activeData.document
781
+        this.activeData.__config__.document
702
         || 'https://element.eleme.cn/#/zh-CN/component/installation'
782
         || 'https://element.eleme.cn/#/zh-CN/component/installation'
703
       )
783
       )
704
     },
784
     },
705
     dateOptions() {
785
     dateOptions() {
706
       if (
786
       if (
707
         this.activeData.type !== undefined
787
         this.activeData.type !== undefined
708
-        && this.activeData.tag === 'el-date-picker'
788
+        && this.activeData.__config__.tag === 'el-date-picker'
709
       ) {
789
       ) {
710
         if (this.activeData['start-placeholder'] === undefined) {
790
         if (this.activeData['start-placeholder'] === undefined) {
711
           return this.dateTypeOptions
791
           return this.dateTypeOptions
@@ -725,17 +805,37 @@ export default {
725
           options: selectComponents
805
           options: selectComponents
726
         }
806
         }
727
       ]
807
       ]
808
+    },
809
+    activeTag() {
810
+      return this.activeData.__config__.tag
811
+    },
812
+    isShowMin() {
813
+      return ['el-input-number', 'el-slider'].indexOf(this.activeTag) > -1
814
+    },
815
+    isShowMax() {
816
+      return ['el-input-number', 'el-slider', 'el-rate'].indexOf(this.activeTag) > -1
817
+    },
818
+    isShowStep() {
819
+      return ['el-input-number', 'el-slider'].indexOf(this.activeTag) > -1
820
+    }
821
+  },
822
+  watch: {
823
+    formConf: {
824
+      handler(val) {
825
+        saveFormConf(val)
826
+      },
827
+      deep: true
728
     }
828
     }
729
   },
829
   },
730
   methods: {
830
   methods: {
731
     addReg() {
831
     addReg() {
732
-      this.activeData.regList.push({
832
+      this.activeData.__config__.regList.push({
733
         pattern: '',
833
         pattern: '',
734
         message: ''
834
         message: ''
735
       })
835
       })
736
     },
836
     },
737
     addSelectItem() {
837
     addSelectItem() {
738
-      this.activeData.options.push({
838
+      this.activeData.__slot__.options.push({
739
         label: '',
839
         label: '',
740
         value: ''
840
         value: ''
741
       })
841
       })
@@ -751,12 +851,12 @@ export default {
751
           <span>{node.label}</span>
851
           <span>{node.label}</span>
752
           <span class="node-operation">
852
           <span class="node-operation">
753
             <i on-click={() => this.append(data)}
853
             <i on-click={() => this.append(data)}
754
-              class="el-icon-plus"
755
-              title="添加"
854
+               class="el-icon-plus"
855
+               title="添加"
756
             ></i>
856
             ></i>
757
             <i on-click={() => this.remove(node, data)}
857
             <i on-click={() => this.remove(node, data)}
758
-              class="el-icon-delete"
759
-              title="删除"
858
+               class="el-icon-delete"
859
+               title="删除"
760
             ></i>
860
             ></i>
761
           </span>
861
           </span>
762
         </div>
862
         </div>
@@ -770,6 +870,7 @@ export default {
770
       this.currentNode = data.children
870
       this.currentNode = data.children
771
     },
871
     },
772
     remove(node, data) {
872
     remove(node, data) {
873
+      this.activeData.__config__.defaultValue = [] // 避免删除时报错
773
       const { parent } = node
874
       const { parent } = node
774
       const children = parent.data.children || parent.data
875
       const children = parent.data.children || parent.data
775
       const index = children.findIndex(d => d.id === data.id)
876
       const index = children.findIndex(d => d.id === data.id)
@@ -785,29 +886,29 @@ export default {
785
       if (Array.isArray(val)) {
886
       if (Array.isArray(val)) {
786
         return val.join(',')
887
         return val.join(',')
787
       }
888
       }
788
-      if (['string', 'number'].indexOf(val) > -1) {
789
-        return val
790
-      }
889
+      // if (['string', 'number'].indexOf(typeof val) > -1) {
890
+      //   return val
891
+      // }
791
       if (typeof val === 'boolean') {
892
       if (typeof val === 'boolean') {
792
         return `${val}`
893
         return `${val}`
793
       }
894
       }
794
       return val
895
       return val
795
     },
896
     },
796
     onDefaultValueInput(str) {
897
     onDefaultValueInput(str) {
797
-      if (isArray(this.activeData.defaultValue)) {
898
+      if (isArray(this.activeData.__config__.defaultValue)) {
798
         // 数组
899
         // 数组
799
         this.$set(
900
         this.$set(
800
-          this.activeData,
901
+          this.activeData.__config__,
801
           'defaultValue',
902
           'defaultValue',
802
           str.split(',').map(val => (isNumberStr(val) ? +val : val))
903
           str.split(',').map(val => (isNumberStr(val) ? +val : val))
803
         )
904
         )
804
       } else if (['true', 'false'].indexOf(str) > -1) {
905
       } else if (['true', 'false'].indexOf(str) > -1) {
805
         // 布尔
906
         // 布尔
806
-        this.$set(this.activeData, 'defaultValue', JSON.parse(str))
907
+        this.$set(this.activeData.__config__, 'defaultValue', JSON.parse(str))
807
       } else {
908
       } else {
808
         // 字符串和数字
909
         // 字符串和数字
809
         this.$set(
910
         this.$set(
810
-          this.activeData,
911
+          this.activeData.__config__,
811
           'defaultValue',
912
           'defaultValue',
812
           isNumberStr(str) ? +str : str
913
           isNumberStr(str) ? +str : str
813
         )
914
         )
@@ -822,7 +923,7 @@ export default {
822
     },
923
     },
823
     setTimeValue(val, type) {
924
     setTimeValue(val, type) {
824
       const valueFormat = type === 'week' ? dateTimeFormat.date : val
925
       const valueFormat = type === 'week' ? dateTimeFormat.date : val
825
-      this.$set(this.activeData, 'defaultValue', null)
926
+      this.$set(this.activeData.__config__, 'defaultValue', null)
826
       this.$set(this.activeData, 'value-format', valueFormat)
927
       this.$set(this.activeData, 'value-format', valueFormat)
827
       this.$set(this.activeData, 'format', val)
928
       this.$set(this.activeData, 'format', val)
828
     },
929
     },
@@ -830,14 +931,14 @@ export default {
830
       this.formConf.span = val
931
       this.formConf.span = val
831
     },
932
     },
832
     multipleChange(val) {
933
     multipleChange(val) {
833
-      this.$set(this.activeData, 'defaultValue', val ? [] : '')
934
+      this.$set(this.activeData.__config__, 'defaultValue', val ? [] : '')
834
     },
935
     },
835
     dateTypeChange(val) {
936
     dateTypeChange(val) {
836
       this.setTimeValue(dateTimeFormat[val], val)
937
       this.setTimeValue(dateTimeFormat[val], val)
837
     },
938
     },
838
     rangeChange(val) {
939
     rangeChange(val) {
839
       this.$set(
940
       this.$set(
840
-        this.activeData,
941
+        this.activeData.__config__,
841
         'defaultValue',
942
         'defaultValue',
842
         val ? [this.activeData.min, this.activeData.max] : this.activeData.min
943
         val ? [this.activeData.min, this.activeData.max] : this.activeData.min
843
       )
944
       )
@@ -849,9 +950,9 @@ export default {
849
       if (val) this.activeData['show-text'] = false
950
       if (val) this.activeData['show-text'] = false
850
     },
951
     },
851
     colorFormatChange(val) {
952
     colorFormatChange(val) {
852
-      this.activeData.defaultValue = null
953
+      this.activeData.__config__.defaultValue = null
853
       this.activeData['show-alpha'] = val.indexOf('a') > -1
954
       this.activeData['show-alpha'] = val.indexOf('a') > -1
854
-      this.activeData.renderKey = +new Date() // 更新renderKey,重新渲染该组件
955
+      this.activeData.__config__.renderKey = +new Date() // 更新renderKey,重新渲染该组件
855
     },
956
     },
856
     openIconsDialog(model) {
957
     openIconsDialog(model) {
857
       this.iconsVisible = true
958
       this.iconsVisible = true
@@ -861,9 +962,14 @@ export default {
861
       this.activeData[this.currentIconModel] = val
962
       this.activeData[this.currentIconModel] = val
862
     },
963
     },
863
     tagChange(tagIcon) {
964
     tagChange(tagIcon) {
864
-      let target = inputComponents.find(item => item.tagIcon === tagIcon)
865
-      if (!target) target = selectComponents.find(item => item.tagIcon === tagIcon)
965
+      let target = inputComponents.find(item => item.__config__.tagIcon === tagIcon)
966
+      if (!target) target = selectComponents.find(item => item.__config__.tagIcon === tagIcon)
866
       this.$emit('tag-change', target)
967
       this.$emit('tag-change', target)
968
+    },
969
+    changeRenderKey() {
970
+      if (needRerenderList.includes(this.activeData.__config__.tag)) {
971
+        this.activeData.__config__.renderKey = +new Date()
972
+      }
867
     }
973
     }
868
   }
974
   }
869
 }
975
 }
@@ -902,7 +1008,7 @@ export default {
902
   margin-top: 4px;
1008
   margin-top: 4px;
903
 }
1009
 }
904
 .select-item.sortable-chosen {
1010
 .select-item.sortable-chosen {
905
-  border: 1px dashed #031527;
1011
+  border: 1px dashed #409eff;
906
 }
1012
 }
907
 .select-line-icon {
1013
 .select-line-icon {
908
   line-height: 32px;
1014
   line-height: 32px;
@@ -929,7 +1035,7 @@ export default {
929
   top: 0;
1035
   top: 0;
930
   left: 0;
1036
   left: 0;
931
   cursor: pointer;
1037
   cursor: pointer;
932
-  background: #031527;
1038
+  background: #409eff;
933
   z-index: 1;
1039
   z-index: 1;
934
   border-radius: 0 0 6px 0;
1040
   border-radius: 0 0 6px 0;
935
   text-align: center;
1041
   text-align: center;

+ 13 - 4
src/views/tool/build/TreeNodeDialog.vue

@@ -59,7 +59,7 @@
59
       <div slot="footer">
59
       <div slot="footer">
60
         <el-button
60
         <el-button
61
           type="primary"
61
           type="primary"
62
-          @click="handleConfirm"
62
+          @click="handelConfirm"
63
         >
63
         >
64
           确定
64
           确定
65
         </el-button>
65
         </el-button>
@@ -71,7 +71,10 @@
71
   </div>
71
   </div>
72
 </template>
72
 </template>
73
 <script>
73
 <script>
74
-import { isNumberStr } from '@/utils/index'
74
+import { isNumberStr } from '@/utils'
75
+import { getTreeNodeId, saveTreeNodeId } from '@/utils/db'
76
+
77
+const id = getTreeNodeId()
75
 
78
 
76
 export default {
79
 export default {
77
   components: {},
80
   components: {},
@@ -79,7 +82,7 @@ export default {
79
   props: [],
82
   props: [],
80
   data() {
83
   data() {
81
     return {
84
     return {
82
-      id: 100,
85
+      id,
83
       formData: {
86
       formData: {
84
         label: undefined,
87
         label: undefined,
85
         value: undefined
88
         value: undefined
@@ -118,6 +121,9 @@ export default {
118
     // eslint-disable-next-line func-names
121
     // eslint-disable-next-line func-names
119
     'formData.value': function (val) {
122
     'formData.value': function (val) {
120
       this.dataType = isNumberStr(val) ? 'number' : 'string'
123
       this.dataType = isNumberStr(val) ? 'number' : 'string'
124
+    },
125
+    id(val) {
126
+      saveTreeNodeId(val)
121
     }
127
     }
122
   },
128
   },
123
   created() {},
129
   created() {},
@@ -133,7 +139,7 @@ export default {
133
     close() {
139
     close() {
134
       this.$emit('update:visible', false)
140
       this.$emit('update:visible', false)
135
     },
141
     },
136
-    handleConfirm() {
142
+    handelConfirm() {
137
       this.$refs.elForm.validate(valid => {
143
       this.$refs.elForm.validate(valid => {
138
         if (!valid) return
144
         if (!valid) return
139
         if (this.dataType === 'number') {
145
         if (this.dataType === 'number') {
@@ -147,3 +153,6 @@ export default {
147
   }
153
   }
148
 }
154
 }
149
 </script>
155
 </script>
156
+
157
+<style lang="scss" scoped>
158
+</style>

File diff suppressed because it is too large
+ 312 - 526
src/views/tool/build/index.vue


+ 1 - 1
vue.config.js

@@ -35,7 +35,7 @@ module.exports = {
35
     proxy: {
35
     proxy: {
36
       // detail: https://cli.vuejs.org/config/#devserver-proxy
36
       // detail: https://cli.vuejs.org/config/#devserver-proxy
37
       [process.env.VUE_APP_BASE_API]: {
37
       [process.env.VUE_APP_BASE_API]: {
38
-        target: `http://192.168.3.200:8080`,
38
+        target: `http://101.42.248.108:17005`,
39
         changeOrigin: true,
39
         changeOrigin: true,
40
         pathRewrite: {
40
         pathRewrite: {
41
           ['^' + process.env.VUE_APP_BASE_API]: ''
41
           ['^' + process.env.VUE_APP_BASE_API]: ''