xm
2024-06-14 722af26bc6fec32bb289b1df51a9016a4935610f
提交 | 用户 | 时间
722af2 1 <template>
X 2   <div class="right-board">
3     <el-tabs v-model="currentTab" class="center-tabs">
4       <el-tab-pane label="组件属性" name="field" />
5       <el-tab-pane label="表单属性" name="form" />
6     </el-tabs>
7     <div class="field-box">
8       <a class="document-link" target="_blank" :href="documentLink" title="查看组件文档">
9         <i class="el-icon-link" />
10       </a>
11       <el-scrollbar class="right-scrollbar">
12         <!-- 组件属性 -->
13         <el-form v-show="currentTab==='field' && showField" size="small" label-width="90px">
14           <el-form-item v-if="activeData.__config__.changeTag" label="组件类型">
15             <el-select
16               v-model="activeData.__config__.tagIcon"
17               placeholder="请选择组件类型"
18               :style="{width: '100%'}"
19               @change="tagChange"
20             >
21               <el-option-group v-for="group in tagList" :key="group.label" :label="group.label">
22                 <el-option
23                   v-for="item in group.options"
24                   :key="item.__config__.label"
25                   :label="item.__config__.label"
26                   :value="item.__config__.tagIcon"
27                 >
28                   <svg-icon class="node-icon" :icon-class="item.__config__.tagIcon" />
29                   <span> {{ item.__config__.label }}</span>
30                 </el-option>
31               </el-option-group>
32             </el-select>
33           </el-form-item>
34           <el-form-item v-if="activeData.__vModel__!==undefined" label="字段名">
35             <el-input v-model="activeData.__vModel__" placeholder="请输入字段名(v-model)" />
36           </el-form-item>
37           <el-form-item v-if="activeData.__config__.componentName!==undefined" label="组件名">
38             {{ activeData.__config__.componentName }}
39           </el-form-item>
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>
43           <el-form-item v-if="activeData.placeholder!==undefined" label="占位提示">
44             <el-input v-model="activeData.placeholder" placeholder="请输入占位提示" @input="changeRenderKey" />
45           </el-form-item>
46           <el-form-item v-if="activeData['start-placeholder']!==undefined" label="开始占位">
47             <el-input v-model="activeData['start-placeholder']" placeholder="请输入占位提示" />
48           </el-form-item>
49           <el-form-item v-if="activeData['end-placeholder']!==undefined" label="结束占位">
50             <el-input v-model="activeData['end-placeholder']" placeholder="请输入占位提示" />
51           </el-form-item>
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>
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="栅格间隔" />
57           </el-form-item>
58           <el-form-item v-if="activeData.__config__.layout==='rowFormItem'&&activeData.type!==undefined" label="布局模式">
59             <el-radio-group v-model="activeData.type">
60               <el-radio-button label="default" />
61               <el-radio-button label="flex" />
62             </el-radio-group>
63           </el-form-item>
64           <el-form-item v-if="activeData.justify!==undefined&&activeData.type==='flex'" label="水平排列">
65             <el-select v-model="activeData.justify" placeholder="请选择水平排列" :style="{width: '100%'}">
66               <el-option
67                 v-for="(item, index) in justifyOptions"
68                 :key="index"
69                 :label="item.label"
70                 :value="item.value"
71               />
72             </el-select>
73           </el-form-item>
74           <el-form-item v-if="activeData.align!==undefined&&activeData.type==='flex'" label="垂直排列">
75             <el-radio-group v-model="activeData.align">
76               <el-radio-button label="top" />
77               <el-radio-button label="middle" />
78               <el-radio-button label="bottom" />
79             </el-radio-group>
80           </el-form-item>
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>
84           <el-form-item v-if="activeData.style&&activeData.style.width!==undefined" label="组件宽度">
85             <el-input v-model="activeData.style.width" placeholder="请输入组件宽度" clearable />
86           </el-form-item>
87           <el-form-item v-if="activeData.__vModel__!==undefined" label="默认值">
88             <el-input
89               :value="setDefaultValue(activeData.__config__.defaultValue)"
90               placeholder="请输入默认值"
91               @input="onDefaultValueInput"
92             />
93           </el-form-item>
94           <el-form-item v-if="activeData.__config__.tag==='el-checkbox-group'" label="至少应选">
95             <el-input-number
96               :value="activeData.min"
97               :min="0"
98               placeholder="至少应选"
99               @input="$set(activeData, 'min', $event?$event:undefined)"
100             />
101           </el-form-item>
102           <el-form-item v-if="activeData.__config__.tag==='el-checkbox-group'" label="最多可选">
103             <el-input-number
104               :value="activeData.max"
105               :min="0"
106               placeholder="最多可选"
107               @input="$set(activeData, 'max', $event?$event:undefined)"
108             />
109           </el-form-item>
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>
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>
116           <el-form-item v-if="activeData['prefix-icon']!==undefined" label="前图标">
117             <el-input v-model="activeData['prefix-icon']" placeholder="请输入前图标名称">
118               <el-button slot="append" icon="el-icon-thumb" @click="openIconsDialog('prefix-icon')">
119                 选择
120               </el-button>
121             </el-input>
122           </el-form-item>
123           <el-form-item v-if="activeData['suffix-icon'] !== undefined" label="后图标">
124             <el-input v-model="activeData['suffix-icon']" placeholder="请输入后图标名称">
125               <el-button slot="append" icon="el-icon-thumb" @click="openIconsDialog('suffix-icon')">
126                 选择
127               </el-button>
128             </el-input>
129           </el-form-item>
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="选项分隔符">
141             <el-input v-model="activeData.separator" placeholder="请输入选项分隔符" />
142           </el-form-item>
143           <el-form-item v-if="activeData.autosize !== undefined" label="最小行数">
144             <el-input-number v-model="activeData.autosize.minRows" :min="1" placeholder="最小行数" />
145           </el-form-item>
146           <el-form-item v-if="activeData.autosize !== undefined" label="最大行数">
147             <el-input-number v-model="activeData.autosize.maxRows" :min="1" placeholder="最大行数" />
148           </el-form-item>
149           <el-form-item v-if="isShowMin" label="最小值">
150             <el-input-number v-model="activeData.min" placeholder="最小值" />
151           </el-form-item>
152           <el-form-item v-if="isShowMax" label="最大值">
153             <el-input-number v-model="activeData.max" placeholder="最大值" />
154           </el-form-item>
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="步长">
159             <el-input-number v-model="activeData.step" placeholder="步数" />
160           </el-form-item>
161           <el-form-item v-if="activeData.__config__.tag === 'el-input-number'" label="精度">
162             <el-input-number v-model="activeData.precision" :min="0" placeholder="精度" />
163           </el-form-item>
164           <el-form-item v-if="activeData.__config__.tag === 'el-input-number'" label="按钮位置">
165             <el-radio-group v-model="activeData['controls-position']">
166               <el-radio-button label="">
167                 默认
168               </el-radio-button>
169               <el-radio-button label="right">
170                 右侧
171               </el-radio-button>
172             </el-radio-group>
173           </el-form-item>
174           <el-form-item v-if="activeData.maxlength !== undefined" label="最多输入">
175             <el-input v-model="activeData.maxlength" placeholder="请输入字符长度">
176               <template slot="append">
177                 个字符
178               </template>
179             </el-input>
180           </el-form-item>
181           <el-form-item v-if="activeData['active-text'] !== undefined" label="开启提示">
182             <el-input v-model="activeData['active-text']" placeholder="请输入开启提示" />
183           </el-form-item>
184           <el-form-item v-if="activeData['inactive-text'] !== undefined" label="关闭提示">
185             <el-input v-model="activeData['inactive-text']" placeholder="请输入关闭提示" />
186           </el-form-item>
187           <el-form-item v-if="activeData['active-value'] !== undefined" label="开启值">
188             <el-input
189               :value="setDefaultValue(activeData['active-value'])"
190               placeholder="请输入开启值"
191               @input="onSwitchValueInput($event, 'active-value')"
192             />
193           </el-form-item>
194           <el-form-item v-if="activeData['inactive-value'] !== undefined" label="关闭值">
195             <el-input
196               :value="setDefaultValue(activeData['inactive-value'])"
197               placeholder="请输入关闭值"
198               @input="onSwitchValueInput($event, 'inactive-value')"
199             />
200           </el-form-item>
201           <el-form-item
202             v-if="activeData.type !== undefined && 'el-date-picker' === activeData.__config__.tag"
203             label="时间类型"
204           >
205             <el-select
206               v-model="activeData.type"
207               placeholder="请选择时间类型"
208               :style="{ width: '100%' }"
209               @change="dateTypeChange"
210             >
211               <el-option
212                 v-for="(item, index) in dateOptions"
213                 :key="index"
214                 :label="item.label"
215                 :value="item.value"
216               />
217             </el-select>
218           </el-form-item>
219           <el-form-item v-if="activeData.name !== undefined" label="文件字段名">
220             <el-input v-model="activeData.name" placeholder="请输入上传文件字段名" />
221           </el-form-item>
222           <el-form-item v-if="activeData.accept !== undefined" label="文件类型">
223             <el-select
224               v-model="activeData.accept"
225               placeholder="请选择文件类型"
226               :style="{ width: '100%' }"
227               clearable
228             >
229               <el-option label="图片" value="image/*" />
230               <el-option label="视频" value="video/*" />
231               <el-option label="音频" value="audio/*" />
232               <el-option label="excel" value=".xls,.xlsx" />
233               <el-option label="word" value=".doc,.docx" />
234               <el-option label="pdf" value=".pdf" />
235               <el-option label="txt" value=".txt" />
236             </el-select>
237           </el-form-item>
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' }">
241                 <el-option label="KB" value="KB" />
242                 <el-option label="MB" value="MB" />
243                 <el-option label="GB" value="GB" />
244               </el-select>
245             </el-input>
246           </el-form-item>
247           <el-form-item v-if="activeData.action !== undefined" label="上传地址">
248             <el-input v-model="activeData.action" placeholder="请输入上传地址" clearable />
249           </el-form-item>
250           <el-form-item v-if="activeData['list-type'] !== undefined" label="列表类型">
251             <el-radio-group v-model="activeData['list-type']" size="small">
252               <el-radio-button label="text">
253                 text
254               </el-radio-button>
255               <el-radio-button label="picture">
256                 picture
257               </el-radio-button>
258               <el-radio-button label="picture-card">
259                 picture-card
260               </el-radio-button>
261             </el-radio-group>
262           </el-form-item>
263           <el-form-item
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"
278             v-show="'picture-card' !== activeData['list-type']"
279             label="按钮文字"
280           >
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="请输入按钮文字" />
288           </el-form-item>
289           <el-form-item v-if="activeData['range-separator'] !== undefined" label="分隔符">
290             <el-input v-model="activeData['range-separator']" placeholder="请输入分隔符" />
291           </el-form-item>
292           <el-form-item v-if="activeData['picker-options'] !== undefined" label="时间段">
293             <el-input
294               v-model="activeData['picker-options'].selectableRange"
295               placeholder="请输入时间段"
296             />
297           </el-form-item>
298           <el-form-item v-if="activeData.format !== undefined" label="时间格式">
299             <el-input
300               :value="activeData.format"
301               placeholder="请输入时间格式"
302               @input="setTimeValue($event)"
303             />
304           </el-form-item>
305           <template v-if="['el-checkbox-group', 'el-radio-group', 'el-select'].indexOf(activeData.__config__.tag) > -1">
306             <el-divider>选项</el-divider>
307             <draggable
308               :list="activeData.__slot__.options"
309               :animation="340"
310               group="selectItem"
311               handle=".option-drag"
312             >
313               <div v-for="(item, index) in activeData.__slot__.options" :key="index" class="select-item">
314                 <div class="select-line-icon option-drag">
315                   <i class="el-icon-s-operation" />
316                 </div>
317                 <el-input v-model="item.label" placeholder="选项名" size="small" />
318                 <el-input
319                   placeholder="选项值"
320                   size="small"
321                   :value="item.value"
322                   @input="setOptionValue(item, $event)"
323                 />
324                 <div class="close-btn select-line-icon" @click="activeData.__slot__.options.splice(index, 1)">
325                   <i class="el-icon-remove-outline" />
326                 </div>
327               </div>
328             </draggable>
329             <div style="margin-left: 20px;">
330               <el-button
331                 style="padding-bottom: 0"
332                 icon="el-icon-circle-plus-outline"
333                 type="text"
334                 @click="addSelectItem"
335               >
336                 添加选项
337               </el-button>
338             </div>
339             <el-divider />
340           </template>
341
342           <template v-if="['el-cascader'].indexOf(activeData.__config__.tag) > -1">
343             <el-divider>选项</el-divider>
344             <el-form-item label="数据类型">
345               <el-radio-group v-model="activeData.__config__.dataType" size="small">
346                 <el-radio-button label="dynamic">
347                   动态数据
348                 </el-radio-button>
349                 <el-radio-button label="static">
350                   静态数据
351                 </el-radio-button>
352               </el-radio-group>
353             </el-form-item>
354
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                 >
363                   <el-select
364                     slot="prepend"
365                     v-model="activeData.__config__.method"
366                     :style="{width: '85px'}"
367                   >
368                     <el-option label="get" value="get" />
369                     <el-option label="post" value="post" />
370                     <el-option label="put" value="put" />
371                     <el-option label="delete" value="delete" />
372                   </el-select>
373                 </el-input>
374               </el-form-item>
375               <el-form-item label="数据位置">
376                 <el-input v-model="activeData.__config__.dataKey" placeholder="请输入标签键名" />
377               </el-form-item>
378               <el-form-item label="标签键名">
379                 <el-input v-model="activeData.props.props.label" placeholder="请输入标签键名" />
380               </el-form-item>
381               <el-form-item label="值键名">
382                 <el-input v-model="activeData.props.props.value" placeholder="请输入值键名" />
383               </el-form-item>
384               <el-form-item label="子级键名">
385                 <el-input v-model="activeData.props.props.children" placeholder="请输入子级键名" />
386               </el-form-item>
387             </template>
388
389             <!-- 级联选择静态树 -->
390             <el-tree
391               v-if="activeData.__config__.dataType === 'static'"
392               draggable
393               :data="activeData.options"
394               node-key="id"
395               :expand-on-click-node="false"
396               :render-content="renderContent"
397             />
398             <div v-if="activeData.__config__.dataType === 'static'" style="margin-left: 20px">
399               <el-button
400                 style="padding-bottom: 0"
401                 icon="el-icon-circle-plus-outline"
402                 type="text"
403                 @click="addTreeItem"
404               >
405                 添加父级
406               </el-button>
407             </div>
408             <el-divider />
409           </template>
410
411           <el-form-item v-if="activeData.__config__.optionType !== undefined" label="选项样式">
412             <el-radio-group v-model="activeData.__config__.optionType">
413               <el-radio-button label="default">
414                 默认
415               </el-radio-button>
416               <el-radio-button label="button">
417                 按钮
418               </el-radio-button>
419             </el-radio-group>
420           </el-form-item>
421           <el-form-item v-if="activeData['active-color'] !== undefined" label="开启颜色">
422             <el-color-picker v-model="activeData['active-color']" />
423           </el-form-item>
424           <el-form-item v-if="activeData['inactive-color'] !== undefined" label="关闭颜色">
425             <el-color-picker v-model="activeData['inactive-color']" />
426           </el-form-item>
427
428           <el-form-item v-if="activeData.__config__.showLabel !== undefined
429             && activeData.__config__.labelWidth !== undefined" label="显示标签"
430           >
431             <el-switch v-model="activeData.__config__.showLabel" />
432           </el-form-item>
433           <el-form-item v-if="activeData.branding !== undefined" label="品牌烙印">
434             <el-switch v-model="activeData.branding" @input="changeRenderKey" />
435           </el-form-item>
436           <el-form-item v-if="activeData['allow-half'] !== undefined" label="允许半选">
437             <el-switch v-model="activeData['allow-half']" />
438           </el-form-item>
439           <el-form-item v-if="activeData['show-text'] !== undefined" label="辅助文字">
440             <el-switch v-model="activeData['show-text']" @change="rateTextChange" />
441           </el-form-item>
442           <el-form-item v-if="activeData['show-score'] !== undefined" label="显示分数">
443             <el-switch v-model="activeData['show-score']" @change="rateScoreChange" />
444           </el-form-item>
445           <el-form-item v-if="activeData['show-stops'] !== undefined" label="显示间断点">
446             <el-switch v-model="activeData['show-stops']" />
447           </el-form-item>
448           <el-form-item v-if="activeData.range !== undefined" label="范围选择">
449             <el-switch v-model="activeData.range" @change="rangeChange" />
450           </el-form-item>
451           <el-form-item
452             v-if="activeData.__config__.border !== undefined && activeData.__config__.optionType === 'default'"
453             label="是否带边框"
454           >
455             <el-switch v-model="activeData.__config__.border" />
456           </el-form-item>
457           <el-form-item v-if="activeData.__config__.tag === 'el-color-picker'" label="颜色格式">
458             <el-select
459               v-model="activeData['color-format']"
460               placeholder="请选择颜色格式"
461               :style="{ width: '100%' }"
462               clearable
463               @change="colorFormatChange"
464             >
465               <el-option
466                 v-for="(item, index) in colorFormatOptions"
467                 :key="index"
468                 :label="item.label"
469                 :value="item.value"
470               />
471             </el-select>
472           </el-form-item>
473           <el-form-item
474             v-if="activeData.size !== undefined &&
475               (activeData.__config__.optionType === 'button' ||
476                 activeData.__config__.border ||
477                 activeData.__config__.tag === 'el-color-picker' ||
478                 activeData.__config__.tag === 'el-button')"
479             label="组件尺寸"
480           >
481             <el-radio-group v-model="activeData.size">
482               <el-radio-button label="medium">
483                 中等
484               </el-radio-button>
485               <el-radio-button label="small">
486                 较小
487               </el-radio-button>
488               <el-radio-button label="mini">
489                 迷你
490               </el-radio-button>
491             </el-radio-group>
492           </el-form-item>
493           <el-form-item v-if="activeData['show-word-limit'] !== undefined" label="输入统计">
494             <el-switch v-model="activeData['show-word-limit']" />
495           </el-form-item>
496           <el-form-item v-if="activeData.__config__.tag === 'el-input-number'" label="严格步数">
497             <el-switch v-model="activeData['step-strictly']" />
498           </el-form-item>
499           <el-form-item v-if="activeData.__config__.tag === 'el-cascader'" label="任选层级">
500             <el-switch v-model="activeData.props.props.checkStrictly" />
501           </el-form-item>
502           <el-form-item v-if="activeData.__config__.tag === 'el-cascader'" label="是否多选">
503             <el-switch v-model="activeData.props.props.multiple" />
504           </el-form-item>
505           <el-form-item v-if="activeData.__config__.tag === 'el-cascader'" label="展示全路径">
506             <el-switch v-model="activeData['show-all-levels']" />
507           </el-form-item>
508           <el-form-item v-if="activeData.__config__.tag === 'el-cascader'" label="可否筛选">
509             <el-switch v-model="activeData.filterable" />
510           </el-form-item>
511           <el-form-item v-if="activeData.clearable !== undefined" label="能否清空">
512             <el-switch v-model="activeData.clearable" />
513           </el-form-item>
514           <el-form-item v-if="activeData.__config__.showTip !== undefined" label="显示提示">
515             <el-switch v-model="activeData.__config__.showTip" />
516           </el-form-item>
517           <el-form-item v-if="activeData.__config__.tag === 'el-upload'" label="多选文件">
518             <el-switch v-model="activeData.multiple" />
519           </el-form-item>
520           <el-form-item v-if="activeData['auto-upload'] !== undefined" label="自动上传">
521             <el-switch v-model="activeData['auto-upload']" />
522           </el-form-item>
523           <el-form-item v-if="activeData.readonly !== undefined" label="是否只读">
524             <el-switch v-model="activeData.readonly" />
525           </el-form-item>
526           <el-form-item v-if="activeData.disabled !== undefined" label="是否禁用">
527             <el-switch v-model="activeData.disabled" />
528           </el-form-item>
529           <el-form-item v-if="activeData.__config__.tag === 'el-select'" label="能否搜索">
530             <el-switch v-model="activeData.filterable" />
531           </el-form-item>
532           <el-form-item v-if="activeData.__config__.tag === 'el-select'" label="是否多选">
533             <el-switch v-model="activeData.multiple" @change="multipleChange" />
534           </el-form-item>
535           <el-form-item v-if="activeData.__config__.required !== undefined" label="是否必填">
536             <el-switch v-model="activeData.__config__.required" />
537           </el-form-item>
538
539           <template v-if="activeData.__config__.layoutTree">
540             <el-divider>布局结构树</el-divider>
541             <el-tree
542               :data="[activeData.__config__]"
543               :props="layoutTreeProps"
544               node-key="renderKey"
545               default-expand-all
546               draggable
547             >
548               <span slot-scope="{ node, data }">
549                 <span class="node-label">
550                   <svg-icon class="node-icon" :icon-class="data.__config__?data.__config__.tagIcon:data.tagIcon" />
551                   {{ node.label }}
552                 </span>
553               </span>
554             </el-tree>
555           </template>
556
557           <template v-if="Array.isArray(activeData.__config__.regList)">
558             <el-divider>正则校验</el-divider>
559             <div
560               v-for="(item, index) in activeData.__config__.regList"
561               :key="index"
562               class="reg-item"
563             >
564               <span class="close-btn" @click="activeData.__config__.regList.splice(index, 1)">
565                 <i class="el-icon-close" />
566               </span>
567               <el-form-item label="表达式">
568                 <el-input v-model="item.pattern" placeholder="请输入正则" />
569               </el-form-item>
570               <el-form-item label="错误提示" style="margin-bottom:0">
571                 <el-input v-model="item.message" placeholder="请输入错误提示" />
572               </el-form-item>
573             </div>
574             <div style="margin-left: 20px">
575               <el-button icon="el-icon-circle-plus-outline" type="text" @click="addReg">
576                 添加规则
577               </el-button>
578             </div>
579           </template>
580         </el-form>
581         <!-- 表单属性 -->
582         <el-form v-show="currentTab === 'form'" size="small" label-width="90px">
583           <el-form-item label="表单名">
584             <el-input v-model="formConf.formRef" placeholder="请输入表单名(ref)" />
585           </el-form-item>
586           <el-form-item label="表单模型">
587             <el-input v-model="formConf.formModel" placeholder="请输入数据模型" />
588           </el-form-item>
589           <el-form-item label="校验模型">
590             <el-input v-model="formConf.formRules" placeholder="请输入校验模型" />
591           </el-form-item>
592           <el-form-item label="表单尺寸">
593             <el-radio-group v-model="formConf.size">
594               <el-radio-button label="medium">
595                 中等
596               </el-radio-button>
597               <el-radio-button label="small">
598                 较小
599               </el-radio-button>
600               <el-radio-button label="mini">
601                 迷你
602               </el-radio-button>
603             </el-radio-group>
604           </el-form-item>
605           <el-form-item label="标签对齐">
606             <el-radio-group v-model="formConf.labelPosition">
607               <el-radio-button label="left">
608                 左对齐
609               </el-radio-button>
610               <el-radio-button label="right">
611                 右对齐
612               </el-radio-button>
613               <el-radio-button label="top">
614                 顶部对齐
615               </el-radio-button>
616             </el-radio-group>
617           </el-form-item>
618           <el-form-item label="标签宽度">
619             <el-input v-model.number="formConf.labelWidth" type="number" placeholder="请输入标签宽度" />
620           </el-form-item>
621           <el-form-item label="栅格间隔">
622             <el-input-number v-model="formConf.gutter" :min="0" placeholder="栅格间隔" />
623           </el-form-item>
624           <el-form-item label="禁用表单">
625             <el-switch v-model="formConf.disabled" />
626           </el-form-item>
627           <el-form-item label="表单按钮">
628             <el-switch v-model="formConf.formBtns" />
629           </el-form-item>
630           <el-form-item label="显示未选中组件边框">
631             <el-switch v-model="formConf.unFocusedComponentBorder" />
632           </el-form-item>
633         </el-form>
634       </el-scrollbar>
635     </div>
636
637     <treeNode-dialog :visible.sync="dialogVisible" title="添加选项" @commit="addNode" />
638     <icons-dialog :visible.sync="iconsVisible" :current="activeData[currentIconModel]" @select="setIcon" />
639   </div>
640 </template>
641
642 <script>
643 import { isArray } from 'util'
644 import TreeNodeDialog from './TreeNodeDialog'
645 import { isNumberStr } from '@/utils/index'
646 import IconsDialog from './IconsDialog'
647 import {
648   inputComponents, selectComponents, layoutComponents
649 } from '@/utils/generator/config'
650 import { saveFormConf } from '@/utils/db'
651
652 const dateTimeFormat = {
653   date: 'yyyy-MM-dd',
654   week: 'yyyy 第 WW 周',
655   month: 'yyyy-MM',
656   year: 'yyyy',
657   datetime: 'yyyy-MM-dd HH:mm:ss',
658   daterange: 'yyyy-MM-dd',
659   monthrange: 'yyyy-MM',
660   datetimerange: 'yyyy-MM-dd HH:mm:ss'
661 }
662
663 // 使changeRenderKey在目标组件改变时可用
664 const needRerenderList = ['tinymce']
665
666 export default {
667   components: {
668     TreeNodeDialog,
669     IconsDialog
670   },
671   props: ['showField', 'activeData', 'formConf'],
672   data() {
673     return {
674       currentTab: 'field',
675       currentNode: null,
676       dialogVisible: false,
677       iconsVisible: false,
678       currentIconModel: null,
679       dateTypeOptions: [
680         {
681           label: '日(date)',
682           value: 'date'
683         },
684         {
685           label: '周(week)',
686           value: 'week'
687         },
688         {
689           label: '月(month)',
690           value: 'month'
691         },
692         {
693           label: '年(year)',
694           value: 'year'
695         },
696         {
697           label: '日期时间(datetime)',
698           value: 'datetime'
699         }
700       ],
701       dateRangeTypeOptions: [
702         {
703           label: '日期范围(daterange)',
704           value: 'daterange'
705         },
706         {
707           label: '月范围(monthrange)',
708           value: 'monthrange'
709         },
710         {
711           label: '日期时间范围(datetimerange)',
712           value: 'datetimerange'
713         }
714       ],
715       colorFormatOptions: [
716         {
717           label: 'hex',
718           value: 'hex'
719         },
720         {
721           label: 'rgb',
722           value: 'rgb'
723         },
724         {
725           label: 'rgba',
726           value: 'rgba'
727         },
728         {
729           label: 'hsv',
730           value: 'hsv'
731         },
732         {
733           label: 'hsl',
734           value: 'hsl'
735         }
736       ],
737       justifyOptions: [
738         {
739           label: 'start',
740           value: 'start'
741         },
742         {
743           label: 'end',
744           value: 'end'
745         },
746         {
747           label: 'center',
748           value: 'center'
749         },
750         {
751           label: 'space-around',
752           value: 'space-around'
753         },
754         {
755           label: 'space-between',
756           value: 'space-between'
757         }
758       ],
759       layoutTreeProps: {
760         label(data, node) {
761           const config = data.__config__
762           return data.componentName || `${config.label}: ${data.__vModel__}`
763         }
764       }
765     }
766   },
767   computed: {
768     documentLink() {
769       return (
770         this.activeData.__config__.document
771         || 'https://element.eleme.cn/#/zh-CN/component/installation'
772       )
773     },
774     dateOptions() {
775       if (
776         this.activeData.type !== undefined
777         && this.activeData.__config__.tag === 'el-date-picker'
778       ) {
779         if (this.activeData['start-placeholder'] === undefined) {
780           return this.dateTypeOptions
781         }
782         return this.dateRangeTypeOptions
783       }
784       return []
785     },
786     tagList() {
787       return [
788         {
789           label: '输入型组件',
790           options: inputComponents
791         },
792         {
793           label: '选择型组件',
794           options: selectComponents
795         }
796       ]
797     },
798     activeTag() {
799       return this.activeData.__config__.tag
800     },
801     isShowMin() {
802       return ['el-input-number', 'el-slider'].indexOf(this.activeTag) > -1
803     },
804     isShowMax() {
805       return ['el-input-number', 'el-slider', 'el-rate'].indexOf(this.activeTag) > -1
806     },
807     isShowStep() {
808       return ['el-input-number', 'el-slider'].indexOf(this.activeTag) > -1
809     }
810   },
811   watch: {
812     formConf: {
813       handler(val) {
814         saveFormConf(val)
815       },
816       deep: true
817     }
818   },
819   methods: {
820     addReg() {
821       this.activeData.__config__.regList.push({
822         pattern: '',
823         message: ''
824       })
825     },
826     addSelectItem() {
827       this.activeData.__slot__.options.push({
828         label: '',
829         value: ''
830       })
831     },
832     addTreeItem() {
833       ++this.idGlobal
834       this.dialogVisible = true
835       this.currentNode = this.activeData.options
836     },
837     renderContent(h, { node, data, store }) {
838       return (
839         <div class="custom-tree-node">
840           <span>{node.label}</span>
841           <span class="node-operation">
842             <i on-click={() => this.append(data)}
843                class="el-icon-plus"
844                title="添加"
845             ></i>
846             <i on-click={() => this.remove(node, data)}
847                class="el-icon-delete"
848                title="删除"
849             ></i>
850           </span>
851         </div>
852       )
853     },
854     append(data) {
855       if (!data.children) {
856         this.$set(data, 'children', [])
857       }
858       this.dialogVisible = true
859       this.currentNode = data.children
860     },
861     remove(node, data) {
862       this.activeData.__config__.defaultValue = [] // 避免删除时报错
863       const { parent } = node
864       const children = parent.data.children || parent.data
865       const index = children.findIndex(d => d.id === data.id)
866       children.splice(index, 1)
867     },
868     addNode(data) {
869       this.currentNode.push(data)
870     },
871     setOptionValue(item, val) {
872       item.value = isNumberStr(val) ? +val : val
873     },
874     setDefaultValue(val) {
875       if (Array.isArray(val)) {
876         return val.join(',')
877       }
878       // if (['string', 'number'].indexOf(typeof val) > -1) {
879       //   return val
880       // }
881       if (typeof val === 'boolean') {
882         return `${val}`
883       }
884       return val
885     },
886     onDefaultValueInput(str) {
887       if (isArray(this.activeData.__config__.defaultValue)) {
888         // 数组
889         this.$set(
890           this.activeData.__config__,
891           'defaultValue',
892           str.split(',').map(val => (isNumberStr(val) ? +val : val))
893         )
894       } else if (['true', 'false'].indexOf(str) > -1) {
895         // 布尔
896         this.$set(this.activeData.__config__, 'defaultValue', JSON.parse(str))
897       } else {
898         // 字符串和数字
899         this.$set(
900           this.activeData.__config__,
901           'defaultValue',
902           isNumberStr(str) ? +str : str
903         )
904       }
905     },
906     onSwitchValueInput(val, name) {
907       if (['true', 'false'].indexOf(val) > -1) {
908         this.$set(this.activeData, name, JSON.parse(val))
909       } else {
910         this.$set(this.activeData, name, isNumberStr(val) ? +val : val)
911       }
912     },
913     setTimeValue(val, type) {
914       const valueFormat = type === 'week' ? dateTimeFormat.date : val
915       this.$set(this.activeData.__config__, 'defaultValue', null)
916       this.$set(this.activeData, 'value-format', valueFormat)
917       this.$set(this.activeData, 'format', val)
918     },
919     spanChange(val) {
920       this.formConf.span = val
921     },
922     multipleChange(val) {
923       this.$set(this.activeData.__config__, 'defaultValue', val ? [] : '')
924     },
925     dateTypeChange(val) {
926       this.setTimeValue(dateTimeFormat[val], val)
927     },
928     rangeChange(val) {
929       this.$set(
930         this.activeData.__config__,
931         'defaultValue',
932         val ? [this.activeData.min, this.activeData.max] : this.activeData.min
933       )
934     },
935     rateTextChange(val) {
936       if (val) this.activeData['show-score'] = false
937     },
938     rateScoreChange(val) {
939       if (val) this.activeData['show-text'] = false
940     },
941     colorFormatChange(val) {
942       this.activeData.__config__.defaultValue = null
943       this.activeData['show-alpha'] = val.indexOf('a') > -1
944       this.activeData.__config__.renderKey = +new Date() // 更新renderKey,重新渲染该组件
945     },
946     openIconsDialog(model) {
947       this.iconsVisible = true
948       this.currentIconModel = model
949     },
950     setIcon(val) {
951       this.activeData[this.currentIconModel] = val
952     },
953     tagChange(tagIcon) {
954       let target = inputComponents.find(item => item.__config__.tagIcon === tagIcon)
955       if (!target) target = selectComponents.find(item => item.__config__.tagIcon === tagIcon)
956       this.$emit('tag-change', target)
957     },
958     changeRenderKey() {
959       if (needRerenderList.includes(this.activeData.__config__.tag)) {
960         this.activeData.__config__.renderKey = +new Date()
961       }
962     }
963   }
964 }
965 </script>
966
967 <style lang="scss" scoped>
968 .right-board {
969   width: 350px;
970   position: absolute;
971   right: 0;
972   top: 0;
973   padding-top: 3px;
974   .field-box {
975     position: relative;
976     height: calc(100vh - 42px);
977     box-sizing: border-box;
978     overflow: hidden;
979   }
980   .el-scrollbar {
981     height: 100%;
982   }
983 }
984 .select-item {
985   display: flex;
986   border: 1px dashed #fff;
987   box-sizing: border-box;
988   & .close-btn {
989     cursor: pointer;
990     color: #f56c6c;
991   }
992   & .el-input + .el-input {
993     margin-left: 4px;
994   }
995 }
996 .select-item + .select-item {
997   margin-top: 4px;
998 }
999 .select-item.sortable-chosen {
1000   border: 1px dashed #409eff;
1001 }
1002 .select-line-icon {
1003   line-height: 32px;
1004   font-size: 22px;
1005   padding: 0 4px;
1006   color: #777;
1007 }
1008 .option-drag {
1009   cursor: move;
1010 }
1011 .time-range {
1012   .el-date-editor {
1013     width: 227px;
1014   }
1015   ::v-deep .el-icon-time {
1016     display: none;
1017   }
1018 }
1019 .document-link {
1020   position: absolute;
1021   display: block;
1022   width: 26px;
1023   height: 26px;
1024   top: 0;
1025   left: 0;
1026   cursor: pointer;
1027   background: #409eff;
1028   z-index: 1;
1029   border-radius: 0 0 6px 0;
1030   text-align: center;
1031   line-height: 26px;
1032   color: #fff;
1033   font-size: 18px;
1034 }
1035 .node-label{
1036   font-size: 14px;
1037 }
1038 .node-icon{
1039   color: #bebfc3;
1040 }
1041 </style>