vue2-client 1.2.55-test3 → 1.2.57

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,752 +1,808 @@
1
- <template>
2
- <a-drawer
3
- title="基础表单配置生成"
4
- placement="right"
5
- :width="isMobile ? screenWidth : screenWidth * 0.85"
6
- :visible="visible"
7
- @close="onClose"
8
- >
9
- <a-row :gutter="24">
10
- <a-col :xl="14" :lg="12" :md="12" :sm="24" :xs="24">
11
- <a-form-model
12
- ref="businessCreateForm"
13
- :rules="rules"
14
- :model="form"
15
- :label-col="labelCol"
16
- :wrapper-col="wrapperCol"
17
- >
18
- <a-form-model-item label="参数组名称" prop="group">
19
- <a-input v-model="form.group" placeholder="设置表单项的组名,如:设置上报参数" />
20
- </a-form-model-item>
21
- <a-form-model-item label="参数组描述" prop="describe">
22
- <a-input v-model="form.describe" placeholder="简单描述参数组,如:用于配置物联网设备的上报参数" />
23
- </a-form-model-item>
24
- <a-form-model-item label="数据字段" prop="column">
25
- <a-button type="primary" @click="addColumnItem()">增加</a-button>
26
- <div v-for="(columnItem, index) in form.column" :key="index">
27
- <a-row :gutter="16">
28
- <a-col :span="16">
29
- <span style="font-weight: bold">{{ columnItem.title }}({{ columnItem.key }})</span>
30
- </a-col>
31
- <a-col v-if="index > 0 && form.column.length > 1" :span="2">
32
- <a-icon type="up-square" @click="upColumnItem(columnItem.key,index)"/>
33
- </a-col>
34
- <a-col v-if="(index !== form.column.length - 1) && form.column.length > 1" :span="2">
35
- <a-icon type="down-square" @click="downColumnItem(columnItem.key,index)"/>
36
- </a-col>
37
- <a-col :span="2">
38
- <a-icon type="edit" @click="editColumnItem(columnItem.key,index)"/>
39
- </a-col>
40
- <a-col :span="2">
41
- <a-icon type="close" @click="removeColumnItem(columnItem.key,index)"/>
42
- </a-col>
43
- </a-row>
44
- </div>
45
- </a-form-model-item>
46
- </a-form-model>
47
- <a-modal
48
- title="数据字段配置"
49
- :visible="dataColumnVisible"
50
- :width="1000"
51
- :zIndex="1001"
52
- @cancel="modelCancel"
53
- @ok="submitItem">
54
- <a-form-model
55
- ref="itemForm"
56
- :rules="itemRules"
57
- :model="item">
58
- <a-row :gutter="16">
59
- <a-col :span="8">
60
- <a-form-model-item label="表单项名" prop="key">
61
- <a-input v-model="item.key" placeholder="请输入表单项名" ref="key">
62
- <a-popover slot="suffix" title="关于表单项名" placement="bottom">
63
- <template slot="content">
64
- <p>设置表单项的名称</p>
65
- </template>
66
- <a-icon type="info-circle" style="color: rgba(0,0,0,.45)" />
67
- </a-popover>
68
- </a-input>
69
- </a-form-model-item>
70
- </a-col>
71
- <a-col :span="8">
72
- <a-form-model-item label="表单项中文名" prop="title">
73
- <a-input v-model="item.title" placeholder="请输入表单项中文名,如:姓名" />
74
- </a-form-model-item>
75
- </a-col>
76
- </a-row>
77
- <template>
78
- <a-row :gutter="16">
79
- <a-col :span="8">
80
- <a-form-model-item label="表单类型" prop="formType">
81
- <a-select v-model="item.formType" placeholder="表单类型,可选">
82
- <a-select-option key="input">输入框</a-select-option>
83
- <a-select-option key="select">选择框</a-select-option>
84
- <a-select-option key="checkbox">多选框</a-select-option>
85
- <a-select-option key="radio">单选框</a-select-option>
86
- <a-select-option key="rangePicker">日期范围选择框</a-select-option>
87
- <a-select-option key="monthPicker">月份选择框</a-select-option>
88
- <a-select-option key="datePicker">单日选择框</a-select-option>
89
- <a-select-option key="cascader">级联选择框(单个下拉)</a-select-option>
90
- <a-select-option key="selects">级联选择框(多个下拉)</a-select-option>
91
- <a-select-option key="textarea">文本域</a-select-option>
92
- <a-select-option key="file">文件上传</a-select-option>
93
- <a-select-option key="image">图片上传</a-select-option>
94
- <a-popover slot="suffixIcon" title="关于表单类型" placement="right">
95
- <template slot="content">
96
- <p>预览设置的表单类型</p>
97
- <a-input-group compact style="width: 400px;">
98
- <a-input value="输入框" style="width: 20%" readOnly/>
99
- <a-input style="width: 80%" placeholder="请输入"/>
100
- </a-input-group>
101
- <br/>
102
- <a-input-group compact style="width: 400px;">
103
- <a-input value="选择框" style="width: 20%" readOnly/>
104
- <a-select style="width: 80%" placeholder="请选择"/>
105
- </a-input-group>
106
- <br/>
107
- <a-input-group compact style="width: 400px;">
108
- <a-input value="多选框" style="width: 20%" readOnly/>
109
- <a-checkbox-group style="margin-left: 10px;margin-top: 5px; width: 70%" :options="['数据1','数据2']"/>
110
- </a-input-group>
111
- <br/>
112
- <a-input-group compact style="width: 400px;">
113
- <a-input value="单选框" style="width: 20%" readOnly/>
114
- <a-radio-group style="margin-left: 10px;margin-top: 5px; width: 70%" :options="[{label: '数据1', value: 'a'},{label: '数据2', value: 'b'}]" name="radioGroup" />
115
- </a-input-group>
116
- <br/>
117
- <a-input-group compact style="width: 400px;">
118
- <a-input value="日期范围选择框" style="width: 20%" readOnly/>
119
- <a-range-picker style="width: 80%" :show-time="true" format="YYYY-MM-DD HH:mm:ss" valueFormat="YYYY-MM-DD HH:mm:ss" />
120
- </a-input-group>
121
- <br/>
122
- <a-input-group compact style="width: 400px;">
123
- <a-input value="月份选择框" style="width: 20%" readOnly/>
124
- <a-month-picker style="width: 80%"/>
125
- </a-input-group>
126
- <br/>
127
- <a-input-group compact style="width: 400px;">
128
- <a-input value="单日选择框" style="width: 20%" readOnly/>
129
- <a-date-picker style="width: 80%"/>
130
- </a-input-group>
131
- <br/>
132
- <a-input-group compact style="width: 400px;">
133
- <a-input value="级联选择框" style="width: 20%" readOnly/>
134
- <a-cascader style="width: 80%" placeholder="请选择"/>
135
- </a-input-group>
136
- <br/>
137
- <a-input-group compact style="width: 400px;">
138
- <a-input value="文本域" style="width: 20%" readOnly/>
139
- <a-textarea style="width: 80%" placeholder="请输入" :rows="1"/>
140
- </a-input-group>
141
- <br/>
142
- <a-input-group compact style="width: 400px;">
143
- <a-input value="文件上传" style="width: 20%" readOnly/>
144
- <a-upload-dragger
145
- name="file"
146
- :multiple="true"
147
- style="margin-left: 5px; width: 75%"
148
- action="https://www.mocky.io/v2/5cc8019d300000980a055e76">
149
- <p class="ant-upload-drag-icon">
150
- <a-icon type="inbox" />
151
- </p>
152
- <p class="ant-upload-text">
153
- 点击或拖动文件到该区域上传
154
- </p>
155
- <p class="ant-upload-hint">
156
- 支持单个或多个文件
157
- </p>
158
- </a-upload-dragger>
159
- </a-input-group>
160
- <br/>
161
- <a-input-group compact style="width: 400px;">
162
- <a-input value="图片上传" style="width: 20%" readOnly/>
163
- <a-upload style="margin-left: 5px; width: 75%" list-type="picture-card" :file-list="[]">
164
- <a-icon type="plus" />
165
- <div class="ant-upload-text">
166
- Upload
167
- </div>
168
- </a-upload>
169
- </a-input-group>
170
- </template>
171
- <a-icon type="info-circle" style="color: rgba(0,0,0,.45)" />
172
- </a-popover>
173
- </a-select>
174
- </a-form-model-item>
175
- </a-col>
176
- <a-col :span="8">
177
- <a-form-model-item
178
- label="表单水印"
179
- prop="placeholder"
180
- v-if="item.formType !== 'checkbox' && item.formType !== 'radio' && item.formType !== 'file' && item.formType !== 'image'">
181
- <a-input v-model="item.placeholder" placeholder="表单水印(placeholder),可选" />
182
- </a-form-model-item>
183
- </a-col>
184
- </a-row>
185
- <a-row :gutter="16" v-if="item.formType === 'file' || item.formType === 'image'">
186
- <a-col :span="8">
187
- <a-form-model-item
188
- label="允许上传文件数量"
189
- prop="accept"
190
- v-if="item.formType === 'file' || item.formType === 'image'">
191
- <a-slider
192
- v-model="item.acceptCount"
193
- :min="1"
194
- :max="20"
195
- :marks="{ 1: '1', 3: '3', 5: '5', 10: '10', 15: '15', 20: '20'}"
196
- :default-value="3"
197
- />
198
- </a-form-model-item>
199
- </a-col>
200
- <a-col :span="8">
201
- <a-form-model-item
202
- label="文件上传模式"
203
- prop="resUploadMode"
204
- v-if="item.formType === 'file' || item.formType === 'image'">
205
- <a-select v-model="item.resUploadMode" placeholder="文件上传模式,默认为服务器" @change="changeFormType(item)">
206
- <a-select-option key="server">服务器</a-select-option>
207
- <a-select-option key="oss">腾讯云对象存储</a-select-option>
208
- <a-select-option key="base64" :disabled="item.formType === 'file'">Base64</a-select-option>
209
- <a-popover slot="suffixIcon" title="关于资源上传模式" placement="right">
210
- <template slot="content">
211
- <p>指定文件上传到服务器,对象存储还是以base64方式存储</p>
212
- <br/>
213
- <p><span style="font-weight: bold">服务器:</span>文件上传到服务器,数据库需存储文件于服务器的路径</p>
214
- <p><span style="font-weight: bold">对象存储:</span>文件上传到云对象存储,数据库需存储文件于对象存储的路径</p>
215
- <p><span style="font-weight: bold">base64:</span>文件以base64字符串方式存入数据库中(仅图片上传表单支持)</p>
216
- </template>
217
- <a-icon type="info-circle" style="color: rgba(0,0,0,.45)" />
218
- </a-popover>
219
- </a-select>
220
- </a-form-model-item>
221
- </a-col>
222
- <a-col :span="8">
223
- <a-form-model-item
224
- label="允许上传文件类型"
225
- prop="accept"
226
- v-if="item.formType === 'file'">
227
- <a-input v-model="item.accept" placeholder="指定文件类型,默认不限制,可选">
228
- <a-popover slot="suffix" title="关于允许上传文件类型" placement="bottom">
229
- <template slot="content">
230
- <p>指定允许上传的文件类型扩展名,如:.doc,.docx等,详情请参考<a target="_blank" @click="visitAcceptFile">允许上传文件类型</a></p>
231
- </template>
232
- <a-icon type="info-circle" style="color: rgba(0,0,0,.45)" />
233
- </a-popover>
234
- </a-input>
235
- </a-form-model-item>
236
- </a-col>
237
- <!-- TODO 配置文件上传表单-所属模块 -->
238
- <!-- TODO 配置文件上传表单-上传扩展目录Key -->
239
- </a-row>
240
- <a-row :gutter="16" v-if="item.formType === 'selects'">
241
- <a-col :span="8">
242
- <a-form-model-item label="数据所属组别" prop="group">
243
- <a-select v-model="item.group" placeholder="请输入数据字段名" ref="group">
244
- <a-select-option v-for="i in groupArray" :key="i">{{ i }}</a-select-option>
245
- <a-popover slot="suffixIcon" title="关于所属组别" placement="bottom">
246
- <template slot="content">
247
- <p>多个下拉框时按照次组别归为一组</p>
248
- </template>
249
- <a-icon type="info-circle" style="color: rgba(0,0,0,.45)" />
250
- </a-popover>
251
- </a-select>
252
- </a-form-model-item>
253
- </a-col>
254
- <a-col :span="8">
255
- <a-form-model-item label="组别内顺序" prop="groupIndex">
256
- <a-select v-model="item.groupIndex" placeholder="表单类型,可选">
257
- <template v-for="i in 5">
258
- <a-select-option :key="i">{{ i }}</a-select-option>
259
- </template>
260
- <a-popover slot="suffix" title="关于组别内顺序" placement="bottom">
261
- <template slot="content">
262
- <p>多个下拉框为一组时,按照此顺序判断页面如何展示以及下拉框得父子顺序</p>
263
- <p>只有顺序为1的数据字段才可以选择数据源类型</p>
264
- </template>
265
- <a-icon type="info-circle" style="color: rgba(0,0,0,.45)" />
266
- </a-popover>
267
- </a-select>
268
- </a-form-model-item>
269
- </a-col>
270
- <a-col :span="8">
271
- <a-form-model-item label="增加组" prop="groupName">
272
- <a-input-search v-model="item.groupName" @search="addGroupName" placeholder="请输入数据字段名" ref="key">
273
- <a-button slot="enterButton">
274
- 新增
275
- </a-button>
276
- </a-input-search>
277
- </a-form-model-item>
278
- </a-col>
279
- </a-row>
280
- <a-row :gutter="16">
281
- <a-col :span="8">
282
- <a-form-model-item label="数据源类型" prop="selectType" v-if="item.formType === 'select' || (item.formType === 'selects' && item.groupIndex == 1) || item.formType === 'cascader'">
283
- <a-select v-model="item.selectType" placeholder="请选择数据源类型" @change="changeSelectKey(item)">
284
- <a-select-option key="key">字典键</a-select-option>
285
- <a-select-option key="fixArray">固定集合</a-select-option>
286
- <a-select-option key="logic">业务逻辑</a-select-option>
287
- <a-popover
288
- slot="suffixIcon"
289
- title="关于下拉框或级联框数据源类型"
290
- placement="bottom">
291
- <template slot="content">
292
- <p>设置下拉框或级联框的数据源</p>
293
- <p>数据源类型分为三种,你可以根据需要选择</p>
294
- <p>字典键:选项从字典表(t_dictionary)获取,你只需要选择字典键的名称即可</p>
295
- <p>业务逻辑名称:选项通过发起http请求调用指定的业务逻辑(Logic)接口获取</p>
296
- <p>固定集合:选项为静态值,JSONArray格式</p>
297
- <p>当表单类型为 " 级联选择框(多个下拉) " 是数据模式为 [{lable,value,children[{lable,value,children[]},{lable,value,children[]}]}] 形式</p>
298
- <p>如:</p>
299
- <json-viewer :value="DemoJson" :expand-depth="parseInt('100')" style="overflow: auto;max-height: 440px"></json-viewer>
300
- </template>
301
- <a-icon type="info-circle" style="color: rgba(0,0,0,.45)" />
302
- </a-popover>
303
- </a-select>
304
- </a-form-model-item>
305
- </a-col>
306
- <a-col :span="8">
307
- <a-form-model-item label="数据源" prop="selectKey" v-if="(item.formType === 'select' || (item.formType === 'selects' && item.groupIndex == 1) || item.formType === 'cascader') && item.selectType">
308
- <a-select
309
- show-search
310
- v-model="item.selectKey"
311
- v-if="item.selectType === 'key'"
312
- placeholder="请选择字典键"
313
- :filter-option="filterOption"
314
- @change="changeSelectKey(item)"
315
- >
316
- <template>
317
- <a-select-option
318
- v-for="(optionItem,index) in option"
319
- :key="index"
320
- :value="Object.keys(optionItem)[0]">{{ optionItem[Object.keys(optionItem)[0]] }}
321
- </a-select-option>
322
- </template>
323
- </a-select>
324
- <a-input v-model="item.selectKey" v-if="item.selectType === 'logic'" placeholder="请输入业务逻辑名称"/>
325
- <a-textarea v-model="item.selectKey" v-if="item.selectType === 'fixArray'" placeholder="请录入数据源" />
326
- </a-form-model-item>
327
- </a-col>
328
- </a-row>
329
- <a-form-model-item label="数据源加载方式" prop="selectLoadType" v-if="item.formType === 'select' && item.selectType === 'logic'">
330
- <a-row :guttor="16">
331
- <a-col :span="8">
332
- <a-radio-group v-model="item.lazyLoad" default-value="false" button-style="solid">
333
- <a-radio-button value="true">
334
- 懒加载搜索
335
- </a-radio-button>
336
- <a-radio-button value="false">
337
- 一次性加载
338
- </a-radio-button>
339
- </a-radio-group>
340
- </a-col>
341
- </a-row>
342
- </a-form-model-item>
343
- <a-form-model-item label="表单校验类型" prop="rule">
344
- <a-row :gutter="16">
345
- <a-col :span="8" v-if="item.formType === 'input' || item.formType === 'textarea'">
346
- <a-select v-model="item.rule.type" placeholder="校验类型,可选">
347
- <a-select-option key="string">字符串</a-select-option>
348
- <a-select-option key="number">数字</a-select-option>
349
- <a-select-option key="boolean">布尔值</a-select-option>
350
- <a-select-option key="regexp">正则表达式</a-select-option>
351
- <a-select-option key="integer">整数</a-select-option>
352
- <a-select-option key="float">小数</a-select-option>
353
- <a-select-option key="array">数组或集合</a-select-option>
354
- <a-select-option key="date">日期</a-select-option>
355
- <a-select-option key="email">邮箱</a-select-option>
356
- <a-popover slot="suffixIcon" title="关于表单校验类型" placement="bottom">
357
- <template slot="content">
358
- <p>设置表单项的校验类型,默认字符串类型</p>
359
- <p>你也可以设置该表单项是否必填</p>
360
- </template>
361
- <a-icon type="info-circle" style="color: rgba(0,0,0,.45)" />
362
- </a-popover>
363
- </a-select>
364
- </a-col>
365
- <a-col :span="8">
366
- <a-radio-group v-model="item.rule.required" default-value="false" button-style="solid">
367
- <a-radio-button value="true">
368
- 必选项
369
- </a-radio-button>
370
- <a-radio-button value="false">
371
- 非必选项
372
- </a-radio-button>
373
- </a-radio-group>
374
- </a-col>
375
- </a-row>
376
- </a-form-model-item>
377
- </template>
378
- </a-form-model>
379
- </a-modal>
380
- <a-button type="primary" @click="view">操作</a-button>
381
- </a-col>
382
- <a-col :xl="10" :lg="12" :md="12" :sm="24" :xs="24">
383
- <a-card :bordered="false" title="预览" size="small" style="overflow: auto">
384
- <json-viewer :copyable="{copyText: '复制', copiedText: '已复制'}" :value="result" :expand-depth="parseInt('100')" style="overflow: auto;max-height: 440px"></json-viewer>
385
- </a-card>
386
- </a-col>
387
- </a-row>
388
- <x-add-form
389
- business-title="效果预览"
390
- business-type="新增"
391
- :visible.sync="modelVisible"
392
- :json-data="formItems"
393
- @onSubmit="submit"/>
394
- </a-drawer>
395
- </template>
396
-
397
- <script>
398
- import XAddForm from '@vue2-client/base-client/components/common/XAddForm/XAddForm'
399
- import JsonViewer from 'vue-json-viewer'
400
- import FileSaver from 'file-saver'
401
- import { queryType } from '@vue2-client/config/CreateQueryConfig'
402
- import { mapState } from 'vuex'
403
- import { commonApi, post } from '@vue2-client/services/api'
404
- const DemoJson = [{ value: 'zhejiang', label: 'Zhejiang', children: [{ value: 'hangzhou', label: 'Hangzhou', children: [{ value: 'xihu', label: 'West Lake' }] }] }]
405
- export default {
406
- name: 'CreateSimpleFormQuery',
407
- components: {
408
- JsonViewer,
409
- XAddForm
410
- },
411
- data () {
412
- return {
413
- DemoJson,
414
- // 页面宽度
415
- screenWidth: document.documentElement.clientWidth,
416
- // 效果预览模态框是否展示
417
- modelVisible: false,
418
- // 数据列配置模态框是否展示
419
- dataColumnVisible: false,
420
- // 数据列操作类型:新增,修改
421
- type: '新增',
422
- labelCol: { span: 4 },
423
- wrapperCol: { span: 14 },
424
- form: {
425
- group: '',
426
- describe: '',
427
- column: []
428
- },
429
- result: {},
430
- item: {
431
- key: '',
432
- title: '',
433
- rule: {
434
- required: 'false'
435
- }
436
- },
437
- itemMap: {},
438
- selectIndex: null,
439
- selectType: undefined,
440
- joinArray: [],
441
- groupArray: ['默认组别'],
442
- rules: {
443
- group: [{ required: true, message: '请输入参数组名称', trigger: 'blur' }],
444
- describe: [{ required: true, message: '请输入参数组描述', trigger: 'blur' }]
445
- },
446
- itemRules: {
447
- key: [{ required: true, message: '请输入表单项名', trigger: 'blur' }],
448
- title: [{ required: true, message: '请输入中文名称', trigger: 'blur' }],
449
- selectType: [{ required: true, message: '请选择数据源类型', trigger: 'change' }],
450
- selectKey: [{ required: true, message: '请输入数据源内容', trigger: 'blur' }]
451
- },
452
- formItems: [],
453
- // 字典键集合
454
- option: []
455
- }
456
- },
457
- mounted () {
458
- this.initView()
459
- },
460
- computed: {
461
- ...mapState('setting', ['isMobile']),
462
- queryTypeV () {
463
- if (this.item.formType) {
464
- return queryType.filter(item => item.match.includes(this.item.formType))
465
- }
466
- return queryType
467
- }
468
- },
469
- props: {
470
- visible: {
471
- type: Boolean,
472
- default: false
473
- },
474
- toEditJson: {
475
- type: Object,
476
- default: () => {}
477
- }
478
- },
479
- watch: {
480
- visible (rel) {
481
- if (rel) {
482
- this.initView()
483
- }
484
- if (rel && this.toEditJson) {
485
- this.form = Object.assign(
486
- {
487
- group: '',
488
- describe: '',
489
- column: []
490
- }, this.toEditJson
491
- )
492
- for (const columnItem of this.form.column) {
493
- // 必选项兼容处理
494
- if (columnItem.rule && columnItem.rule.required && columnItem.rule.required !== 'false') {
495
- columnItem.rule.required = columnItem.rule.required.toString()
496
- } else {
497
- if (!columnItem.rule) {
498
- columnItem.rule = {}
499
- }
500
- columnItem.rule.required = 'false'
501
- }
502
- // 数据源加载方式兼容处理
503
- if (columnItem.lazyLoad && columnItem.lazyLoad !== 'false') {
504
- columnItem.lazyLoad = columnItem.lazyLoad.toString()
505
- } else {
506
- columnItem.lazyLoad = 'false'
507
- }
508
- // 下拉框数据源兼容处理
509
- if ((columnItem.formType === 'select' || columnItem.formType === 'cascader') && columnItem.selectKey) {
510
- // 数据源为logic
511
- if (columnItem.selectKey.toString().startsWith('logic@')) {
512
- columnItem.selectType = 'logic'
513
- } else if (columnItem.selectKey instanceof Array || this.isJSON(columnItem.selectKey)) {
514
- // 数据源为固定json集合
515
- if (columnItem.selectKey instanceof Array) {
516
- columnItem.selectKey = JSON.stringify(columnItem.selectKey)
517
- }
518
- columnItem.selectType = 'fixArray'
519
- } else {
520
- columnItem.selectType = 'key'
521
- }
522
- }
523
- this.itemMap[columnItem.key] = Object.assign({
524
- key: '',
525
- title: '',
526
- rule: {
527
- required: 'false'
528
- }
529
- }, columnItem)
530
- }
531
- }
532
- }
533
- },
534
- methods: {
535
- // 添加多个下拉框分组标识符
536
- addGroupName (val) {
537
- this.item.groupName = undefined
538
- if (!this.groupArray.find(item => item === val)) {
539
- this.groupArray.push(val)
540
- }
541
- },
542
- // 初始化组件
543
- initView () {
544
- this.result = {}
545
- post(commonApi.getDictionaryParam, {}).then(res => {
546
- this.option = res
547
- })
548
- },
549
- onClose () {
550
- this.$emit('update:visible', false)
551
- },
552
- filterOption (input, option) {
553
- return (
554
- option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
555
- )
556
- },
557
- onModelClose () {
558
- this.modelVisible = false
559
- },
560
- addColumnItem () {
561
- this.type = '新增'
562
- this.dataColumnVisible = true
563
- },
564
- editColumnItem (key, index) {
565
- if (this.itemMap[key]) {
566
- this.type = '修改'
567
- this.item = Object.assign({ formType: 'input', type: 'string' }, this.itemMap[key])
568
- this.selectIndex = index
569
- this.dataColumnVisible = true
570
- } else {
571
- this.$message.warn('编辑失败')
572
- }
573
- },
574
- removeColumnItem (key, index) {
575
- const _this = this
576
- this.$confirm({
577
- title: '您确定要删除该数据项?',
578
- content: '删除的数据项无法恢复',
579
- okText: '确定',
580
- okType: 'danger',
581
- cancelText: '取消',
582
- onOk () {
583
- delete _this.itemMap[key]
584
- _this.form.column.splice(index, 1)
585
- }
586
- })
587
- },
588
- upColumnItem (key, index) {
589
- const newIndex = index - 1
590
- const itemA = this.form.column[newIndex]
591
- const itemB = this.form.column[index]
592
- this.form.column.splice(index, 1, itemA)
593
- this.form.column.splice(newIndex, 1, itemB)
594
- },
595
- downColumnItem (key, index) {
596
- const newIndex = index + 1
597
- const itemA = this.form.column[newIndex]
598
- const itemB = this.form.column[index]
599
- this.form.column.splice(index, 1, itemA)
600
- this.form.column.splice(newIndex, 1, itemB)
601
- },
602
- submitItem () {
603
- this.$refs.itemForm.validate(valid => {
604
- if (valid) {
605
- this.itemHandle()
606
- }
607
- })
608
- },
609
- itemHandle () {
610
- const str = JSON.stringify(this.item)
611
- const item = JSON.parse(str)
612
- this.itemMap[item.key] = JSON.parse(str)
613
- // 表单类型为输入框
614
- if (item.formType && item.formType === 'input') {
615
- delete item.formType
616
- }
617
- // 校验类型
618
- if (item.rule.required) {
619
- item.rule.required = item.rule.required.toString() === 'true'
620
- } else {
621
- item.rule.required = false
622
- }
623
- // 下拉框
624
- if ((item.formType === 'select' || (item.formType === 'selects' && item.groupIndex == '1') || item.formType === 'cascader') && item.selectKey) {
625
- // 数据源为logic
626
- if (item.selectType === 'logic') {
627
- // 如果已经有了 logic@ 将不再拼接
628
- if (item.selectKey.substring(0, 6) !== 'logic@') {
629
- item.selectKey = 'logic@' + item.selectKey
630
- }
631
- if (!item.lazyLoad) {
632
- delete item.lazyLoad
633
- }
634
- } else if (item.selectType === 'fixArray') {
635
- // 数据源为固定json集合
636
- if (!this.isJSON(item.selectKey)) {
637
- this.$message.warning('下拉框数据源不是JSON集合')
638
- return
639
- }
640
- delete item.lazyLoad
641
- } else {
642
- delete item.lazyLoad
643
- }
644
- if (item.formType !== 'selects') {
645
- delete item.selectType
646
- }
647
- delete item.lazyLoad
648
- } else {
649
- if (item.formType !== 'selects') {
650
- delete item.group
651
- delete item.groupIndex
652
- }
653
- delete item.selectType
654
- delete item.selectKey
655
- delete item.selectKeyName
656
- delete item.lazyLoad
657
- }
658
- if (this.type === '新增') {
659
- this.form.column.push(item)
660
- } else {
661
- this.form.column[this.selectIndex] = item
662
- }
663
- this.item = {
664
- key: '',
665
- title: '',
666
- rule: {
667
- required: 'false'
668
- }
669
- }
670
- this.$message.success('增加成功')
671
- this.dataColumnVisible = false
672
- },
673
- // 判断是否为json字符串
674
- isJSON (str) {
675
- if (typeof str == 'string') {
676
- try {
677
- const obj = JSON.parse(str)
678
- return !!(typeof obj == 'object' && obj)
679
- } catch (e) {
680
- return false
681
- }
682
- }
683
- },
684
- exportJson () {
685
- const data = JSON.stringify(this.form, null, 2)
686
- const blob = new Blob([data], { type: 'application/json' })
687
- FileSaver.saveAs(blob, `SimpleFormQuery.json`)
688
- this.$message.success('导出成功!')
689
- },
690
- viewHandle (then) {
691
- if (this.form.column.length === 0) {
692
- this.$message.error('你没有增加任何数据字段')
693
- return
694
- }
695
- this.result = JSON.parse(JSON.stringify(this.form))
696
- for (const item of this.result.column) {
697
- if (item.selectType === 'fixArray') {
698
- item.selectKey = JSON.parse(item.selectKey)
699
- }
700
- }
701
- then()
702
- },
703
- view () {
704
- this.$refs.businessCreateForm.validate(valid => {
705
- if (valid) {
706
- this.viewHandle(() => {
707
- post(commonApi.getColumnsJson, { queryObject: this.result }).then(res => {
708
- this.formItems = res.formJson
709
- this.modelVisible = true
710
- })
711
- })
712
- }
713
- })
714
- },
715
- submit () {
716
- this.onModelClose()
717
- this.$refs.businessCreateForm.validate(valid => {
718
- if (valid) {
719
- this.viewHandle(() => {
720
- // saveQueryParams
721
- this.$emit('saveSimpleFormQueryParams', this.result)
722
- })
723
- }
724
- })
725
- },
726
- modelCancel () {
727
- this.dataColumnVisible = false
728
- // 延迟是为了避免编辑数据窗口关闭时重置表单导致的闪烁
729
- setTimeout(() => {
730
- this.item = {
731
- key: '',
732
- title: '',
733
- rule: {
734
- required: 'false'
735
- }
736
- }
737
- }, 100)
738
- },
739
- changeSelectKey (item) {
740
- if (item.selectType === 'key' && item.selectKey) {
741
- item.slot.type = 'badge'
742
- item.slotKeyMap = item.selectKey
743
- }
744
- },
745
- visitAcceptFile () {
746
- window.open('https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/input/file#attr-accept')
747
- }
748
- }
749
- }
750
- </script>
751
- <style lang="less" scoped>
752
- </style>
1
+ <template>
2
+ <a-drawer
3
+ title="基础表单配置生成"
4
+ placement="right"
5
+ :width="isMobile ? screenWidth : screenWidth * 0.85"
6
+ :visible="visible"
7
+ @close="onClose"
8
+ >
9
+ <a-row :gutter="24">
10
+ <a-col :xl="14" :lg="12" :md="12" :sm="24" :xs="24">
11
+ <a-form-model
12
+ ref="businessCreateForm"
13
+ :rules="rules"
14
+ :model="form"
15
+ :label-col="labelCol"
16
+ :wrapper-col="wrapperCol"
17
+ >
18
+ <a-form-model-item label="参数组名称" prop="group">
19
+ <a-input v-model="form.group" placeholder="设置表单项的组名,如:设置上报参数" />
20
+ </a-form-model-item>
21
+ <a-form-model-item label="参数组描述" prop="describe">
22
+ <a-input v-model="form.describe" placeholder="简单描述参数组,如:用于配置物联网设备的上报参数" />
23
+ </a-form-model-item>
24
+ <a-form-model-item label="数据字段" prop="column">
25
+ <a-button type="primary" @click="addColumnItem()">增加</a-button>
26
+ <div v-for="(columnItem, index) in form.column" :key="index">
27
+ <a-row :gutter="16">
28
+ <a-col :span="16">
29
+ <span style="font-weight: bold">{{ columnItem.title }}({{ columnItem.key }})</span>
30
+ </a-col>
31
+ <a-col v-if="index > 0 && form.column.length > 1" :span="2">
32
+ <a-icon type="up-square" @click="upColumnItem(columnItem.key,index)"/>
33
+ </a-col>
34
+ <a-col v-if="(index !== form.column.length - 1) && form.column.length > 1" :span="2">
35
+ <a-icon type="down-square" @click="downColumnItem(columnItem.key,index)"/>
36
+ </a-col>
37
+ <a-col :span="2">
38
+ <a-icon type="edit" @click="editColumnItem(columnItem.key,index)"/>
39
+ </a-col>
40
+ <a-col :span="2">
41
+ <a-icon type="close" @click="removeColumnItem(columnItem.key,index)"/>
42
+ </a-col>
43
+ </a-row>
44
+ </div>
45
+ </a-form-model-item>
46
+ </a-form-model>
47
+ <a-modal
48
+ title="数据字段配置"
49
+ :visible="dataColumnVisible"
50
+ :width="1000"
51
+ :zIndex="1001"
52
+ @cancel="modelCancel"
53
+ @ok="submitItem">
54
+ <a-form-model
55
+ ref="itemForm"
56
+ :rules="itemRules"
57
+ :model="item">
58
+ <a-row :gutter="16">
59
+ <a-col :span="8">
60
+ <a-form-model-item label="表单项名" prop="key">
61
+ <a-input v-model="item.key" placeholder="请输入表单项名" ref="key" :disabled="item.formType === 'file' || item.formType === 'image'">
62
+ <a-popover slot="suffix" title="关于表单项名" placement="bottom">
63
+ <template slot="content">
64
+ <p>设置表单项的名称</p>
65
+ </template>
66
+ <a-icon type="info-circle" style="color: rgba(0,0,0,.45)" />
67
+ </a-popover>
68
+ </a-input>
69
+ </a-form-model-item>
70
+ </a-col>
71
+ <a-col :span="8">
72
+ <a-form-model-item label="表单项中文名" prop="title">
73
+ <a-input v-model="item.title" placeholder="请输入表单项中文名,如:姓名" />
74
+ </a-form-model-item>
75
+ </a-col>
76
+ </a-row>
77
+ <template>
78
+ <a-row :gutter="16">
79
+ <a-col :span="8">
80
+ <a-form-model-item label="表单类型" prop="formType">
81
+ <a-select v-model="item.formType" placeholder="表单类型,可选" @change="changeFormType(item)">
82
+ <a-select-option key="input">输入框</a-select-option>
83
+ <a-select-option key="select">选择框</a-select-option>
84
+ <a-select-option key="checkbox">多选框</a-select-option>
85
+ <a-select-option key="radio">单选框</a-select-option>
86
+ <a-select-option key="rangePicker">日期范围选择框</a-select-option>
87
+ <a-select-option key="monthPicker">月份选择框</a-select-option>
88
+ <a-select-option key="datePicker">单日选择框</a-select-option>
89
+ <a-select-option key="cascader">级联选择框(单个下拉)</a-select-option>
90
+ <a-select-option key="selects">级联选择框(多个下拉)</a-select-option>
91
+ <a-select-option key="textarea">文本域</a-select-option>
92
+ <a-select-option key="file">文件上传</a-select-option>
93
+ <a-select-option key="image">图片上传</a-select-option>
94
+ <a-popover slot="suffixIcon" title="关于表单类型" placement="right">
95
+ <template slot="content">
96
+ <p>预览设置的表单类型</p>
97
+ <a-input-group compact style="width: 400px;">
98
+ <a-input value="输入框" style="width: 20%" readOnly/>
99
+ <a-input style="width: 80%" placeholder="请输入"/>
100
+ </a-input-group>
101
+ <br/>
102
+ <a-input-group compact style="width: 400px;">
103
+ <a-input value="选择框" style="width: 20%" readOnly/>
104
+ <a-select style="width: 80%" placeholder="请选择"/>
105
+ </a-input-group>
106
+ <br/>
107
+ <a-input-group compact style="width: 400px;">
108
+ <a-input value="多选框" style="width: 20%" readOnly/>
109
+ <a-checkbox-group style="margin-left: 10px;margin-top: 5px; width: 70%" :options="['数据1','数据2']"/>
110
+ </a-input-group>
111
+ <br/>
112
+ <a-input-group compact style="width: 400px;">
113
+ <a-input value="单选框" style="width: 20%" readOnly/>
114
+ <a-radio-group style="margin-left: 10px;margin-top: 5px; width: 70%" :options="[{label: '数据1', value: 'a'},{label: '数据2', value: 'b'}]" name="radioGroup" />
115
+ </a-input-group>
116
+ <br/>
117
+ <a-input-group compact style="width: 400px;">
118
+ <a-input value="日期范围选择框" style="width: 20%" readOnly/>
119
+ <a-range-picker style="width: 80%" :show-time="true" format="YYYY-MM-DD HH:mm:ss" valueFormat="YYYY-MM-DD HH:mm:ss" />
120
+ </a-input-group>
121
+ <br/>
122
+ <a-input-group compact style="width: 400px;">
123
+ <a-input value="月份选择框" style="width: 20%" readOnly/>
124
+ <a-month-picker style="width: 80%"/>
125
+ </a-input-group>
126
+ <br/>
127
+ <a-input-group compact style="width: 400px;">
128
+ <a-input value="单日选择框" style="width: 20%" readOnly/>
129
+ <a-date-picker style="width: 80%"/>
130
+ </a-input-group>
131
+ <br/>
132
+ <a-input-group compact style="width: 400px;">
133
+ <a-input value="级联选择框" style="width: 20%" readOnly/>
134
+ <a-cascader style="width: 80%" placeholder="请选择"/>
135
+ </a-input-group>
136
+ <br/>
137
+ <a-input-group compact style="width: 400px;">
138
+ <a-input value="文本域" style="width: 20%" readOnly/>
139
+ <a-textarea style="width: 80%" placeholder="请输入" :rows="1"/>
140
+ </a-input-group>
141
+ <br/>
142
+ <a-input-group compact style="width: 400px;">
143
+ <a-input value="文件上传" style="width: 20%" readOnly/>
144
+ <a-upload-dragger
145
+ name="file"
146
+ :multiple="true"
147
+ style="margin-left: 5px; width: 75%"
148
+ action="https://www.mocky.io/v2/5cc8019d300000980a055e76">
149
+ <p class="ant-upload-drag-icon">
150
+ <a-icon type="inbox" />
151
+ </p>
152
+ <p class="ant-upload-text">
153
+ 点击或拖动文件到该区域上传
154
+ </p>
155
+ <p class="ant-upload-hint">
156
+ 支持单个或多个文件
157
+ </p>
158
+ </a-upload-dragger>
159
+ </a-input-group>
160
+ <br/>
161
+ <a-input-group compact style="width: 400px;">
162
+ <a-input value="图片上传" style="width: 20%" readOnly/>
163
+ <a-upload style="margin-left: 5px; width: 75%" list-type="picture-card" :file-list="[]">
164
+ <a-icon type="plus" />
165
+ <div class="ant-upload-text">
166
+ Upload
167
+ </div>
168
+ </a-upload>
169
+ </a-input-group>
170
+ </template>
171
+ <a-icon type="info-circle" style="color: rgba(0,0,0,.45)" />
172
+ </a-popover>
173
+ </a-select>
174
+ </a-form-model-item>
175
+ </a-col>
176
+ <a-col :span="8">
177
+ <a-form-model-item
178
+ label="表单水印"
179
+ prop="placeholder"
180
+ v-if="item.formType !== 'checkbox' && item.formType !== 'radio' && item.formType !== 'file' && item.formType !== 'image'">
181
+ <a-input v-model="item.placeholder" placeholder="表单水印(placeholder),可选" />
182
+ </a-form-model-item>
183
+ </a-col>
184
+ </a-row>
185
+ <a-row :gutter="16" v-if="item.formType === 'file' || item.formType === 'image'">
186
+ <a-col :span="8">
187
+ <a-form-model-item
188
+ label="允许上传文件数量"
189
+ prop="accept"
190
+ v-if="item.formType === 'file' || item.formType === 'image'">
191
+ <a-slider
192
+ v-model="item.acceptCount"
193
+ :min="1"
194
+ :max="20"
195
+ :marks="{ 1: '1', 3: '3', 5: '5', 10: '10', 15: '15', 20: '20'}"
196
+ :default-value="3"
197
+ />
198
+ </a-form-model-item>
199
+ </a-col>
200
+ <a-col :span="8">
201
+ <a-form-model-item label="上传的仓库" prop="resUploadStock">
202
+ <a-select v-model="item.resUploadStock" placeholder="选择文件上传到的仓库" @change="changeStock">
203
+ <a-select-option v-for="stock in stockList" :key="stock.id">{{ stock.f_name }}</a-select-option>
204
+ </a-select>
205
+ </a-form-model-item>
206
+ </a-col>
207
+ <a-col :span="8">
208
+ <a-form-model-item v-if="item.resUploadStock" label="具体路径" prop="pathKey">
209
+ <a-select v-model="item.pathKey" placeholder="仓库扩展路径">
210
+ <a-select-option v-for="pathKey in lowerPath" :key="pathKey.label">{{ pathKey.label }}</a-select-option>
211
+ </a-select>
212
+ </a-form-model-item>
213
+ </a-col>
214
+ <a-col :span="8">
215
+ <a-form-model-item
216
+ label="文件上传模式"
217
+ prop="resUploadMode"
218
+ v-if="item.formType === 'file' || item.formType === 'image'">
219
+ <a-select v-model="item.resUploadMode" placeholder="文件上传模式,默认为服务器" @change="changeFormType(item)">
220
+ <a-select-option key="server">服务器</a-select-option>
221
+ <a-select-option key="oss">腾讯云对象存储</a-select-option>
222
+ <a-select-option key="base64" :disabled="item.formType === 'file'">Base64</a-select-option>
223
+ <a-popover slot="suffixIcon" title="关于资源上传模式" placement="right">
224
+ <template slot="content">
225
+ <p>指定文件上传到服务器,对象存储还是以base64方式存储</p>
226
+ <br/>
227
+ <p><span style="font-weight: bold">服务器:</span>文件上传到服务器,数据库需存储文件于服务器的路径</p>
228
+ <p><span style="font-weight: bold">对象存储:</span>文件上传到云对象存储,数据库需存储文件于对象存储的路径</p>
229
+ <p><span style="font-weight: bold">base64:</span>文件以base64字符串方式存入数据库中(仅图片上传表单支持)</p>
230
+ </template>
231
+ <a-icon type="info-circle" style="color: rgba(0,0,0,.45)" />
232
+ </a-popover>
233
+ </a-select>
234
+ </a-form-model-item>
235
+ </a-col>
236
+ <a-col :span="8">
237
+ <a-form-model-item
238
+ label="允许上传文件类型"
239
+ prop="accept"
240
+ v-if="item.formType === 'file'">
241
+ <a-input v-model="item.accept" placeholder="指定文件类型,默认不限制,可选">
242
+ <a-popover slot="suffix" title="关于允许上传文件类型" placement="bottom">
243
+ <template slot="content">
244
+ <p>指定允许上传的文件类型扩展名,如:.doc,.docx等,详情请参考<a target="_blank" @click="visitAcceptFile">允许上传文件类型</a></p>
245
+ </template>
246
+ <a-icon type="info-circle" style="color: rgba(0,0,0,.45)" />
247
+ </a-popover>
248
+ </a-input>
249
+ </a-form-model-item>
250
+ </a-col>
251
+ <!-- TODO 配置文件上传表单-所属模块 -->
252
+ <!-- TODO 配置文件上传表单-上传扩展目录Key -->
253
+ </a-row>
254
+ <a-row :gutter="16" v-if="item.formType === 'selects'">
255
+ <a-col :span="8">
256
+ <a-form-model-item label="数据所属组别" prop="group">
257
+ <a-select v-model="item.group" placeholder="请输入数据字段名" ref="group">
258
+ <a-select-option v-for="i in groupArray" :key="i">{{ i }}</a-select-option>
259
+ <a-popover slot="suffixIcon" title="关于所属组别" placement="bottom">
260
+ <template slot="content">
261
+ <p>多个下拉框时按照次组别归为一组</p>
262
+ </template>
263
+ <a-icon type="info-circle" style="color: rgba(0,0,0,.45)" />
264
+ </a-popover>
265
+ </a-select>
266
+ </a-form-model-item>
267
+ </a-col>
268
+ <a-col :span="8">
269
+ <a-form-model-item label="组别内顺序" prop="groupIndex">
270
+ <a-select v-model="item.groupIndex" placeholder="表单类型,可选">
271
+ <template v-for="i in 5">
272
+ <a-select-option :key="i">{{ i }}</a-select-option>
273
+ </template>
274
+ <a-popover slot="suffix" title="关于组别内顺序" placement="bottom">
275
+ <template slot="content">
276
+ <p>多个下拉框为一组时,按照此顺序判断页面如何展示以及下拉框得父子顺序</p>
277
+ <p>只有顺序为1的数据字段才可以选择数据源类型</p>
278
+ </template>
279
+ <a-icon type="info-circle" style="color: rgba(0,0,0,.45)" />
280
+ </a-popover>
281
+ </a-select>
282
+ </a-form-model-item>
283
+ </a-col>
284
+ <a-col :span="8">
285
+ <a-form-model-item label="增加组" prop="groupName">
286
+ <a-input-search v-model="item.groupName" @search="addGroupName" placeholder="请输入数据字段名" ref="key">
287
+ <a-button slot="enterButton">
288
+ 新增
289
+ </a-button>
290
+ </a-input-search>
291
+ </a-form-model-item>
292
+ </a-col>
293
+ </a-row>
294
+ <a-row :gutter="16">
295
+ <a-col :span="8">
296
+ <a-form-model-item label="数据源类型" prop="selectType" v-if="item.formType === 'select' || (item.formType === 'selects' && item.groupIndex == 1) || item.formType === 'cascader'">
297
+ <a-select v-model="item.selectType" placeholder="请选择数据源类型" @change="changeSelectKey(item)">
298
+ <a-select-option key="key">字典键</a-select-option>
299
+ <a-select-option key="fixArray">固定集合</a-select-option>
300
+ <a-select-option key="logic">业务逻辑</a-select-option>
301
+ <a-popover
302
+ slot="suffixIcon"
303
+ title="关于下拉框或级联框数据源类型"
304
+ placement="bottom">
305
+ <template slot="content">
306
+ <p>设置下拉框或级联框的数据源</p>
307
+ <p>数据源类型分为三种,你可以根据需要选择</p>
308
+ <p>字典键:选项从字典表(t_dictionary)获取,你只需要选择字典键的名称即可</p>
309
+ <p>业务逻辑名称:选项通过发起http请求调用指定的业务逻辑(Logic)接口获取</p>
310
+ <p>固定集合:选项为静态值,JSONArray格式</p>
311
+ <p>当表单类型为 " 级联选择框(多个下拉) " 是数据模式为 [{lable,value,children[{lable,value,children[]},{lable,value,children[]}]}] 形式</p>
312
+ <p>如:</p>
313
+ <json-viewer :value="DemoJson" :expand-depth="parseInt('100')" style="overflow: auto;max-height: 440px"></json-viewer>
314
+ </template>
315
+ <a-icon type="info-circle" style="color: rgba(0,0,0,.45)" />
316
+ </a-popover>
317
+ </a-select>
318
+ </a-form-model-item>
319
+ </a-col>
320
+ <a-col :span="8">
321
+ <a-form-model-item label="数据源" prop="selectKey" v-if="(item.formType === 'select' || (item.formType === 'selects' && item.groupIndex == 1) || item.formType === 'cascader') && item.selectType">
322
+ <a-select
323
+ show-search
324
+ v-model="item.selectKey"
325
+ v-if="item.selectType === 'key'"
326
+ placeholder="请选择字典键"
327
+ :filter-option="filterOption"
328
+ @change="changeSelectKey(item)"
329
+ >
330
+ <template>
331
+ <a-select-option
332
+ v-for="(optionItem,index) in option"
333
+ :key="index"
334
+ :value="Object.keys(optionItem)[0]">{{ optionItem[Object.keys(optionItem)[0]] }}
335
+ </a-select-option>
336
+ </template>
337
+ </a-select>
338
+ <a-input v-model="item.selectKey" v-if="item.selectType === 'logic'" placeholder="请输入业务逻辑名称"/>
339
+ <a-textarea v-model="item.selectKey" v-if="item.selectType === 'fixArray'" placeholder="请录入数据源" />
340
+ </a-form-model-item>
341
+ </a-col>
342
+ </a-row>
343
+ <a-form-model-item label="数据源加载方式" prop="selectLoadType" v-if="item.formType === 'select' && item.selectType === 'logic'">
344
+ <a-row :guttor="16">
345
+ <a-col :span="8">
346
+ <a-radio-group v-model="item.lazyLoad" default-value="false" button-style="solid">
347
+ <a-radio-button value="true">
348
+ 懒加载搜索
349
+ </a-radio-button>
350
+ <a-radio-button value="false">
351
+ 一次性加载
352
+ </a-radio-button>
353
+ </a-radio-group>
354
+ </a-col>
355
+ </a-row>
356
+ </a-form-model-item>
357
+ <a-form-model-item label="表单校验类型" prop="rule">
358
+ <a-row :gutter="16">
359
+ <a-col :span="8" v-if="item.formType === 'input' || item.formType === 'textarea'">
360
+ <a-select v-model="item.rule.type" placeholder="校验类型,可选">
361
+ <a-select-option key="string">字符串</a-select-option>
362
+ <a-select-option key="number">数字</a-select-option>
363
+ <a-select-option key="boolean">布尔值</a-select-option>
364
+ <a-select-option key="regexp">正则表达式</a-select-option>
365
+ <a-select-option key="integer">整数</a-select-option>
366
+ <a-select-option key="float">小数</a-select-option>
367
+ <a-select-option key="array">数组或集合</a-select-option>
368
+ <a-select-option key="date">日期</a-select-option>
369
+ <a-select-option key="email">邮箱</a-select-option>
370
+ <a-popover slot="suffixIcon" title="关于表单校验类型" placement="bottom">
371
+ <template slot="content">
372
+ <p>设置表单项的校验类型,默认字符串类型</p>
373
+ <p>你也可以设置该表单项是否必填</p>
374
+ </template>
375
+ <a-icon type="info-circle" style="color: rgba(0,0,0,.45)" />
376
+ </a-popover>
377
+ </a-select>
378
+ </a-col>
379
+ <a-col :span="8">
380
+ <a-radio-group v-model="item.rule.required" default-value="false" button-style="solid">
381
+ <a-radio-button value="true">
382
+ 必选项
383
+ </a-radio-button>
384
+ <a-radio-button value="false">
385
+ 非必选项
386
+ </a-radio-button>
387
+ </a-radio-group>
388
+ </a-col>
389
+ </a-row>
390
+ </a-form-model-item>
391
+ </template>
392
+ </a-form-model>
393
+ </a-modal>
394
+ <a-button type="primary" @click="view">操作</a-button>
395
+ </a-col>
396
+ <a-col :xl="10" :lg="12" :md="12" :sm="24" :xs="24">
397
+ <a-card :bordered="false" title="预览" size="small" style="overflow: auto">
398
+ <json-viewer :copyable="{copyText: '复制', copiedText: '已复制'}" :value="result" :expand-depth="parseInt('100')" style="overflow: auto;max-height: 440px"></json-viewer>
399
+ </a-card>
400
+ </a-col>
401
+ </a-row>
402
+ <x-add-form
403
+ business-title="效果预览"
404
+ business-type="新增"
405
+ :visible.sync="modelVisible"
406
+ :json-data="formItems"
407
+ @onSubmit="submit"/>
408
+ </a-drawer>
409
+ </template>
410
+
411
+ <script>
412
+ import XAddForm from '@vue2-client/base-client/components/common/XAddForm/XAddForm'
413
+ import JsonViewer from 'vue-json-viewer'
414
+ import FileSaver from 'file-saver'
415
+ import { queryType } from '@vue2-client/config/CreateQueryConfig'
416
+ import { mapState } from 'vuex'
417
+ import { commonApi, post } from '@vue2-client/services/api'
418
+ const DemoJson = [{ value: 'zhejiang', label: 'Zhejiang', children: [{ value: 'hangzhou', label: 'Hangzhou', children: [{ value: 'xihu', label: 'West Lake' }] }] }]
419
+ export default {
420
+ name: 'CreateSimpleFormQuery',
421
+ components: {
422
+ JsonViewer,
423
+ XAddForm
424
+ },
425
+ data () {
426
+ return {
427
+ DemoJson,
428
+ // 页面宽度
429
+ screenWidth: document.documentElement.clientWidth,
430
+ // 效果预览模态框是否展示
431
+ modelVisible: false,
432
+ // 数据列配置模态框是否展示
433
+ dataColumnVisible: false,
434
+ // 数据列操作类型:新增,修改
435
+ type: '新增',
436
+ labelCol: { span: 4 },
437
+ wrapperCol: { span: 14 },
438
+ form: {
439
+ group: '',
440
+ describe: '',
441
+ column: []
442
+ },
443
+ lowerPath: [],
444
+ stockList: [],
445
+ result: {},
446
+ item: {
447
+ key: '',
448
+ title: '',
449
+ fileRootPath: undefined,
450
+ resUploadStock: undefined,
451
+ pathKey: undefined,
452
+ accept: undefined,
453
+ rule: {
454
+ required: 'false'
455
+ }
456
+ },
457
+ itemMap: {},
458
+ selectIndex: null,
459
+ selectType: undefined,
460
+ joinArray: [],
461
+ groupArray: ['默认组别'],
462
+ rules: {
463
+ group: [{ required: true, message: '请输入参数组名称', trigger: 'blur' }],
464
+ describe: [{ required: true, message: '请输入参数组描述', trigger: 'blur' }]
465
+ },
466
+ itemRules: {
467
+ key: [{ required: true, message: '请输入表单项名', trigger: 'blur' }],
468
+ title: [{ required: true, message: '请输入中文名称', trigger: 'blur' }],
469
+ selectType: [{ required: true, message: '请选择数据源类型', trigger: 'change' }],
470
+ selectKey: [{ required: true, message: '请输入数据源内容', trigger: 'blur' }]
471
+ },
472
+ formItems: [],
473
+ // 字典键集合
474
+ option: []
475
+ }
476
+ },
477
+ mounted () {
478
+ this.initView()
479
+ this.getStocks()
480
+ },
481
+ computed: {
482
+ ...mapState('setting', ['isMobile']),
483
+ queryTypeV () {
484
+ if (this.item.formType) {
485
+ return queryType.filter(item => item.match.includes(this.item.formType))
486
+ }
487
+ return queryType
488
+ }
489
+ },
490
+ props: {
491
+ visible: {
492
+ type: Boolean,
493
+ default: false
494
+ },
495
+ toEditJson: {
496
+ type: Object,
497
+ default: () => {}
498
+ }
499
+ },
500
+ watch: {
501
+ visible (rel) {
502
+ if (rel) {
503
+ this.initView()
504
+ }
505
+ if (rel && this.toEditJson) {
506
+ this.form = Object.assign(
507
+ {
508
+ group: '',
509
+ describe: '',
510
+ column: []
511
+ }, this.toEditJson
512
+ )
513
+ for (const columnItem of this.form.column) {
514
+ // 必选项兼容处理
515
+ if (columnItem.rule && columnItem.rule.required && columnItem.rule.required !== 'false') {
516
+ columnItem.rule.required = columnItem.rule.required.toString()
517
+ } else {
518
+ if (!columnItem.rule) {
519
+ columnItem.rule = {}
520
+ }
521
+ columnItem.rule.required = 'false'
522
+ }
523
+ // 数据源加载方式兼容处理
524
+ if (columnItem.lazyLoad && columnItem.lazyLoad !== 'false') {
525
+ columnItem.lazyLoad = columnItem.lazyLoad.toString()
526
+ } else {
527
+ columnItem.lazyLoad = 'false'
528
+ }
529
+ // 下拉框数据源兼容处理
530
+ if ((columnItem.formType === 'select' || columnItem.formType === 'cascader') && columnItem.selectKey) {
531
+ // 数据源为logic
532
+ if (columnItem.selectKey.toString().startsWith('logic@')) {
533
+ columnItem.selectType = 'logic'
534
+ } else if (columnItem.selectKey instanceof Array || this.isJSON(columnItem.selectKey)) {
535
+ // 数据源为固定json集合
536
+ if (columnItem.selectKey instanceof Array) {
537
+ columnItem.selectKey = JSON.stringify(columnItem.selectKey)
538
+ }
539
+ columnItem.selectType = 'fixArray'
540
+ } else {
541
+ columnItem.selectType = 'key'
542
+ }
543
+ }
544
+ this.itemMap[columnItem.key] = Object.assign({
545
+ key: '',
546
+ title: '',
547
+ rule: {
548
+ required: 'false'
549
+ }
550
+ }, columnItem)
551
+ }
552
+ }
553
+ }
554
+ },
555
+ methods: {
556
+ // 添加多个下拉框分组标识符
557
+ addGroupName (val) {
558
+ this.item.groupName = undefined
559
+ if (!this.groupArray.find(item => item === val)) {
560
+ this.groupArray.push(val)
561
+ }
562
+ },
563
+ // 初始化组件
564
+ initView () {
565
+ this.result = {}
566
+ post(commonApi.getDictionaryParam, {}).then(res => {
567
+ this.option = res
568
+ })
569
+ },
570
+ onClose () {
571
+ this.$emit('update:visible', false)
572
+ },
573
+ filterOption (input, option) {
574
+ return (
575
+ option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
576
+ )
577
+ },
578
+ onModelClose () {
579
+ this.modelVisible = false
580
+ },
581
+ addColumnItem () {
582
+ this.type = '新增'
583
+ this.dataColumnVisible = true
584
+ },
585
+ editColumnItem (key, index) {
586
+ if (this.itemMap[key]) {
587
+ this.type = '修改'
588
+ this.item = Object.assign({ formType: 'input', type: 'string' }, this.itemMap[key])
589
+ this.selectIndex = index
590
+ this.dataColumnVisible = true
591
+ } else {
592
+ this.$message.warn('编辑失败')
593
+ }
594
+ },
595
+ removeColumnItem (key, index) {
596
+ const _this = this
597
+ this.$confirm({
598
+ title: '您确定要删除该数据项?',
599
+ content: '删除的数据项无法恢复',
600
+ okText: '确定',
601
+ okType: 'danger',
602
+ cancelText: '取消',
603
+ onOk () {
604
+ delete _this.itemMap[key]
605
+ _this.form.column.splice(index, 1)
606
+ }
607
+ })
608
+ },
609
+ upColumnItem (key, index) {
610
+ const newIndex = index - 1
611
+ const itemA = this.form.column[newIndex]
612
+ const itemB = this.form.column[index]
613
+ this.form.column.splice(index, 1, itemA)
614
+ this.form.column.splice(newIndex, 1, itemB)
615
+ },
616
+ downColumnItem (key, index) {
617
+ const newIndex = index + 1
618
+ const itemA = this.form.column[newIndex]
619
+ const itemB = this.form.column[index]
620
+ this.form.column.splice(index, 1, itemA)
621
+ this.form.column.splice(newIndex, 1, itemB)
622
+ },
623
+ submitItem () {
624
+ this.$refs.itemForm.validate(valid => {
625
+ if (valid) {
626
+ this.itemHandle()
627
+ }
628
+ })
629
+ },
630
+ itemHandle () {
631
+ const str = JSON.stringify(this.item)
632
+ const item = JSON.parse(str)
633
+ this.itemMap[item.key] = JSON.parse(str)
634
+ // 表单类型为输入框
635
+ if (item.formType && item.formType === 'input') {
636
+ delete item.formType
637
+ }
638
+ // 校验类型
639
+ if (item.rule.required) {
640
+ item.rule.required = item.rule.required.toString() === 'true'
641
+ } else {
642
+ item.rule.required = false
643
+ }
644
+ // 下拉框
645
+ if ((item.formType === 'select' || (item.formType === 'selects' && item.groupIndex == '1') || item.formType === 'cascader') && item.selectKey) {
646
+ // 数据源为logic
647
+ if (item.selectType === 'logic') {
648
+ // 如果已经有了 logic@ 将不再拼接
649
+ if (item.selectKey.substring(0, 6) !== 'logic@') {
650
+ item.selectKey = 'logic@' + item.selectKey
651
+ }
652
+ if (!item.lazyLoad) {
653
+ delete item.lazyLoad
654
+ }
655
+ } else if (item.selectType === 'fixArray') {
656
+ // 数据源为固定json集合
657
+ if (!this.isJSON(item.selectKey)) {
658
+ this.$message.warning('下拉框数据源不是JSON集合')
659
+ return
660
+ }
661
+ delete item.lazyLoad
662
+ } else {
663
+ delete item.lazyLoad
664
+ }
665
+ if (item.formType !== 'selects') {
666
+ delete item.selectType
667
+ }
668
+ delete item.lazyLoad
669
+ } else {
670
+ if (item.formType !== 'selects') {
671
+ delete item.group
672
+ delete item.groupIndex
673
+ }
674
+ delete item.selectType
675
+ delete item.selectKey
676
+ delete item.selectKeyName
677
+ delete item.lazyLoad
678
+ }
679
+ if (this.type === '新增') {
680
+ this.form.column.push(item)
681
+ } else {
682
+ this.form.column[this.selectIndex] = item
683
+ }
684
+ this.item = {
685
+ key: '',
686
+ title: '',
687
+ rule: {
688
+ required: 'false'
689
+ }
690
+ }
691
+ this.$message.success('增加成功')
692
+ this.dataColumnVisible = false
693
+ },
694
+ // 判断是否为json字符串
695
+ isJSON (str) {
696
+ if (typeof str == 'string') {
697
+ try {
698
+ const obj = JSON.parse(str)
699
+ return !!(typeof obj == 'object' && obj)
700
+ } catch (e) {
701
+ return false
702
+ }
703
+ }
704
+ },
705
+ exportJson () {
706
+ const data = JSON.stringify(this.form, null, 2)
707
+ const blob = new Blob([data], { type: 'application/json' })
708
+ FileSaver.saveAs(blob, `SimpleFormQuery.json`)
709
+ this.$message.success('导出成功!')
710
+ },
711
+ viewHandle (then) {
712
+ if (this.form.column.length === 0) {
713
+ this.$message.error('你没有增加任何数据字段')
714
+ return
715
+ }
716
+ this.result = JSON.parse(JSON.stringify(this.form))
717
+ for (const item of this.result.column) {
718
+ if (item.selectType === 'fixArray') {
719
+ item.selectKey = JSON.parse(item.selectKey)
720
+ }
721
+ }
722
+ then()
723
+ },
724
+ view () {
725
+ this.$refs.businessCreateForm.validate(valid => {
726
+ if (valid) {
727
+ this.viewHandle(() => {
728
+ post(commonApi.getColumnsJson, { queryObject: this.result }).then(res => {
729
+ this.formItems = res.formJson
730
+ this.modelVisible = true
731
+ })
732
+ })
733
+ }
734
+ })
735
+ },
736
+ submit () {
737
+ this.onModelClose()
738
+ this.$refs.businessCreateForm.validate(valid => {
739
+ if (valid) {
740
+ this.viewHandle(() => {
741
+ // saveQueryParams
742
+ this.$emit('saveSimpleFormQueryParams', this.result)
743
+ })
744
+ }
745
+ })
746
+ },
747
+ // 修改上传到哪个仓库
748
+ changeStock (stock) {
749
+ if (stock) {
750
+ const stockValue = this.stockList.filter(item => item.id === stock)[0]
751
+ this.lowerPath = stockValue.f_lower_path_json ?? []
752
+ this.item.resUploadMode = stockValue.f_stock_type
753
+ this.item.fileRootPath = stockValue.f_root_path
754
+ this.item.stockAlias = stockValue.f_alias
755
+ this.item.pathKey = undefined
756
+ }
757
+ },
758
+ // 获取所有仓库
759
+ getStocks () {
760
+ if (this.stockList.length === 0) {
761
+ post('/webmeterapi/getFilesStock', {}).then(res => {
762
+ this.stockList = res.sort((a, b) => b.progress - a.progress)
763
+ }).catch(e => {})
764
+ }
765
+ },
766
+ modelCancel () {
767
+ this.dataColumnVisible = false
768
+ // 延迟是为了避免编辑数据窗口关闭时重置表单导致的闪烁
769
+ setTimeout(() => {
770
+ this.item = {
771
+ key: '',
772
+ title: '',
773
+ rule: {
774
+ required: 'false'
775
+ }
776
+ }
777
+ }, 100)
778
+ },
779
+ changeSelectKey (item) {
780
+ if (item.selectType === 'key' && item.selectKey) {
781
+ item.slot.type = 'badge'
782
+ item.slotKeyMap = item.selectKey
783
+ }
784
+ },
785
+ visitAcceptFile () {
786
+ window.open('https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/input/file#attr-accept')
787
+ },
788
+ changeFormType (item) {
789
+ console.log('=====')
790
+ if (item.formType === 'file' || item.formType === 'image') {
791
+ this.item.acceptCount = 3
792
+ this.getStocks()
793
+ this.item.accept = item.formType === 'file' ? ['*'] : ['.jpg,.jpeg,.ico,.gif,svg,.webp,.png,.bmp,.pjpeg,']
794
+ this.item.resUploadMode = 'server'
795
+ this.item.key = item.formType === 'file' ? 'FilesId' : 'Images'
796
+ } else {
797
+ if (['FilesId', 'Images'].includes(this.item.key)) { this.item.key = '' }
798
+ // 表单查询方式有预选项时
799
+ if (this.queryTypeV.length === 1) {
800
+ this.item.queryType = this.queryTypeV[0].value
801
+ }
802
+ }
803
+ },
804
+ }
805
+ }
806
+ </script>
807
+ <style lang="less" scoped>
808
+ </style>