Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
jinli gu
RuoYi Vue
Commits
cb0a4b78
Commit
cb0a4b78
authored
Feb 24, 2020
by
RuoYi
Browse files
若依 2.1
parent
46a16952
Changes
61
Hide whitespace changes
Inline
Side-by-side
ruoyi-ui/src/views/tool/build/IconsDialog.vue
0 → 100644
View file @
cb0a4b78
<
template
>
<div
class=
"icon-dialog"
>
<el-dialog
v-bind=
"$attrs"
width=
"980px"
:modal-append-to-body=
"false"
v-on=
"$listeners"
@
open=
"onOpen"
@
close=
"onClose"
>
<div
slot=
"title"
>
选择图标
<el-input
v-model=
"key"
size=
"mini"
:style=
"
{width: '260px'}"
placeholder="请输入图标名称"
prefix-icon="el-icon-search"
clearable
/>
</div>
<ul
class=
"icon-ul"
>
<li
v-for=
"icon in iconList"
:key=
"icon"
:class=
"active===icon?'active-item':''"
@
click=
"onSelect(icon)"
>
<i
:class=
"icon"
/>
<div>
{{
icon
}}
</div>
</li>
</ul>
</el-dialog>
</div>
</
template
>
<
script
>
import
iconList
from
'
@/utils/generator/icon.json
'
const
originList
=
iconList
.
map
(
name
=>
`el-icon-
${
name
}
`
)
export
default
{
inheritAttrs
:
false
,
props
:
[
'
current
'
],
data
()
{
return
{
iconList
:
originList
,
active
:
null
,
key
:
''
}
},
watch
:
{
key
(
val
)
{
if
(
val
)
{
this
.
iconList
=
originList
.
filter
(
name
=>
name
.
indexOf
(
val
)
>
-
1
)
}
else
{
this
.
iconList
=
originList
}
}
},
methods
:
{
onOpen
()
{
this
.
active
=
this
.
current
this
.
key
=
''
},
onClose
()
{},
onSelect
(
icon
)
{
this
.
active
=
icon
this
.
$emit
(
'
select
'
,
icon
)
this
.
$emit
(
'
update:visible
'
,
false
)
}
}
}
</
script
>
<
style
lang=
"scss"
scoped
>
.icon-ul
{
margin
:
0
;
padding
:
0
;
font-size
:
0
;
li
{
list-style-type
:
none
;
text-align
:
center
;
font-size
:
14px
;
display
:
inline-block
;
width
:
16
.66%
;
box-sizing
:
border-box
;
height
:
108px
;
padding
:
15px
6px
6px
6px
;
cursor
:
pointer
;
overflow
:
hidden
;
&
:hover
{
background
:
#f2f2f2
;
}
&
.active-item
{
background
:
#e1f3fb
;
color
:
#7a6df0
}
>
i
{
font-size
:
30px
;
line-height
:
50px
;
}
}
}
.icon-dialog
{
::v-deep
.el-dialog
{
border-radius
:
8px
;
margin-bottom
:
0
;
margin-top
:
4vh
!
important
;
display
:
flex
;
flex-direction
:
column
;
max-height
:
92vh
;
overflow
:
hidden
;
box-sizing
:
border-box
;
.el-dialog__header
{
padding-top
:
14px
;
}
.el-dialog__body
{
margin
:
0
20px
20px
20px
;
padding
:
0
;
overflow
:
auto
;
}
}
}
</
style
>
ruoyi-ui/src/views/tool/build/RightPanel.vue
0 → 100644
View file @
cb0a4b78
<
template
>
<div
class=
"right-board"
>
<el-tabs
v-model=
"currentTab"
class=
"center-tabs"
>
<el-tab-pane
label=
"组件属性"
name=
"field"
/>
<el-tab-pane
label=
"表单属性"
name=
"form"
/>
</el-tabs>
<div
class=
"field-box"
>
<a
class=
"document-link"
target=
"_blank"
:href=
"documentLink"
title=
"查看组件文档"
>
<i
class=
"el-icon-link"
/>
</a>
<el-scrollbar
class=
"right-scrollbar"
>
<!-- 组件属性 -->
<el-form
v-show=
"currentTab==='field' && showField"
size=
"small"
label-width=
"90px"
>
<el-form-item
v-if=
"activeData.changeTag"
label=
"组件类型"
>
<el-select
v-model=
"activeData.tagIcon"
placeholder=
"请选择组件类型"
:style=
"
{width: '100%'}"
@change="tagChange"
>
<el-option-group
v-for=
"group in tagList"
:key=
"group.label"
:label=
"group.label"
>
<el-option
v-for=
"item in group.options"
:key=
"item.label"
:label=
"item.label"
:value=
"item.tagIcon"
>
<svg-icon
class=
"node-icon"
:icon-class=
"item.tagIcon"
/>
<span>
{{
item
.
label
}}
</span>
</el-option>
</el-option-group>
</el-select>
</el-form-item>
<el-form-item
v-if=
"activeData.vModel!==undefined"
label=
"字段名"
>
<el-input
v-model=
"activeData.vModel"
placeholder=
"请输入字段名(v-model)"
/>
</el-form-item>
<el-form-item
v-if=
"activeData.componentName!==undefined"
label=
"组件名"
>
{{
activeData
.
componentName
}}
</el-form-item>
<el-form-item
v-if=
"activeData.label!==undefined"
label=
"标题"
>
<el-input
v-model=
"activeData.label"
placeholder=
"请输入标题"
/>
</el-form-item>
<el-form-item
v-if=
"activeData.placeholder!==undefined"
label=
"占位提示"
>
<el-input
v-model=
"activeData.placeholder"
placeholder=
"请输入占位提示"
/>
</el-form-item>
<el-form-item
v-if=
"activeData['start-placeholder']!==undefined"
label=
"开始占位"
>
<el-input
v-model=
"activeData['start-placeholder']"
placeholder=
"请输入占位提示"
/>
</el-form-item>
<el-form-item
v-if=
"activeData['end-placeholder']!==undefined"
label=
"结束占位"
>
<el-input
v-model=
"activeData['end-placeholder']"
placeholder=
"请输入占位提示"
/>
</el-form-item>
<el-form-item
v-if=
"activeData.span!==undefined"
label=
"表单栅格"
>
<el-slider
v-model=
"activeData.span"
:max=
"24"
:min=
"1"
:marks=
"
{12:''}" @change="spanChange" />
</el-form-item>
<el-form-item
v-if=
"activeData.layout==='rowFormItem'"
label=
"栅格间隔"
>
<el-input-number
v-model=
"activeData.gutter"
:min=
"0"
placeholder=
"栅格间隔"
/>
</el-form-item>
<el-form-item
v-if=
"activeData.layout==='rowFormItem'"
label=
"布局模式"
>
<el-radio-group
v-model=
"activeData.type"
>
<el-radio-button
label=
"default"
/>
<el-radio-button
label=
"flex"
/>
</el-radio-group>
</el-form-item>
<el-form-item
v-if=
"activeData.justify!==undefined&&activeData.type==='flex'"
label=
"水平排列"
>
<el-select
v-model=
"activeData.justify"
placeholder=
"请选择水平排列"
:style=
"
{width: '100%'}">
<el-option
v-for=
"(item, index) in justifyOptions"
:key=
"index"
:label=
"item.label"
:value=
"item.value"
/>
</el-select>
</el-form-item>
<el-form-item
v-if=
"activeData.align!==undefined&&activeData.type==='flex'"
label=
"垂直排列"
>
<el-radio-group
v-model=
"activeData.align"
>
<el-radio-button
label=
"top"
/>
<el-radio-button
label=
"middle"
/>
<el-radio-button
label=
"bottom"
/>
</el-radio-group>
</el-form-item>
<el-form-item
v-if=
"activeData.labelWidth!==undefined"
label=
"标签宽度"
>
<el-input
v-model.number=
"activeData.labelWidth"
type=
"number"
placeholder=
"请输入标签宽度"
/>
</el-form-item>
<el-form-item
v-if=
"activeData.style&&activeData.style.width!==undefined"
label=
"组件宽度"
>
<el-input
v-model=
"activeData.style.width"
placeholder=
"请输入组件宽度"
clearable
/>
</el-form-item>
<el-form-item
v-if=
"activeData.vModel!==undefined"
label=
"默认值"
>
<el-input
:value=
"setDefaultValue(activeData.defaultValue)"
placeholder=
"请输入默认值"
@
input=
"onDefaultValueInput"
/>
</el-form-item>
<el-form-item
v-if=
"activeData.tag==='el-checkbox-group'"
label=
"至少应选"
>
<el-input-number
:value=
"activeData.min"
:min=
"0"
placeholder=
"至少应选"
@
input=
"$set(activeData, 'min', $event?$event:undefined)"
/>
</el-form-item>
<el-form-item
v-if=
"activeData.tag==='el-checkbox-group'"
label=
"最多可选"
>
<el-input-number
:value=
"activeData.max"
:min=
"0"
placeholder=
"最多可选"
@
input=
"$set(activeData, 'max', $event?$event:undefined)"
/>
</el-form-item>
<el-form-item
v-if=
"activeData.prepend!==undefined"
label=
"前缀"
>
<el-input
v-model=
"activeData.prepend"
placeholder=
"请输入前缀"
/>
</el-form-item>
<el-form-item
v-if=
"activeData.append!==undefined"
label=
"后缀"
>
<el-input
v-model=
"activeData.append"
placeholder=
"请输入后缀"
/>
</el-form-item>
<el-form-item
v-if=
"activeData['prefix-icon']!==undefined"
label=
"前图标"
>
<el-input
v-model=
"activeData['prefix-icon']"
placeholder=
"请输入前图标名称"
>
<el-button
slot=
"append"
icon=
"el-icon-thumb"
@
click=
"openIconsDialog('prefix-icon')"
>
选择
</el-button>
</el-input>
</el-form-item>
<el-form-item
v-if=
"activeData['suffix-icon'] !== undefined"
label=
"后图标"
>
<el-input
v-model=
"activeData['suffix-icon']"
placeholder=
"请输入后图标名称"
>
<el-button
slot=
"append"
icon=
"el-icon-thumb"
@
click=
"openIconsDialog('suffix-icon')"
>
选择
</el-button>
</el-input>
</el-form-item>
<el-form-item
v-if=
"activeData.tag === 'el-cascader'"
label=
"选项分隔符"
>
<el-input
v-model=
"activeData.separator"
placeholder=
"请输入选项分隔符"
/>
</el-form-item>
<el-form-item
v-if=
"activeData.autosize !== undefined"
label=
"最小行数"
>
<el-input-number
v-model=
"activeData.autosize.minRows"
:min=
"1"
placeholder=
"最小行数"
/>
</el-form-item>
<el-form-item
v-if=
"activeData.autosize !== undefined"
label=
"最大行数"
>
<el-input-number
v-model=
"activeData.autosize.maxRows"
:min=
"1"
placeholder=
"最大行数"
/>
</el-form-item>
<el-form-item
v-if=
"activeData.min !== undefined"
label=
"最小值"
>
<el-input-number
v-model=
"activeData.min"
placeholder=
"最小值"
/>
</el-form-item>
<el-form-item
v-if=
"activeData.max !== undefined"
label=
"最大值"
>
<el-input-number
v-model=
"activeData.max"
placeholder=
"最大值"
/>
</el-form-item>
<el-form-item
v-if=
"activeData.step !== undefined"
label=
"步长"
>
<el-input-number
v-model=
"activeData.step"
placeholder=
"步数"
/>
</el-form-item>
<el-form-item
v-if=
"activeData.tag === 'el-input-number'"
label=
"精度"
>
<el-input-number
v-model=
"activeData.precision"
:min=
"0"
placeholder=
"精度"
/>
</el-form-item>
<el-form-item
v-if=
"activeData.tag === 'el-input-number'"
label=
"按钮位置"
>
<el-radio-group
v-model=
"activeData['controls-position']"
>
<el-radio-button
label=
""
>
默认
</el-radio-button>
<el-radio-button
label=
"right"
>
右侧
</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item
v-if=
"activeData.maxlength !== undefined"
label=
"最多输入"
>
<el-input
v-model=
"activeData.maxlength"
placeholder=
"请输入字符长度"
>
<template
slot=
"append"
>
个字符
</
template
>
</el-input>
</el-form-item>
<el-form-item
v-if=
"activeData['active-text'] !== undefined"
label=
"开启提示"
>
<el-input
v-model=
"activeData['active-text']"
placeholder=
"请输入开启提示"
/>
</el-form-item>
<el-form-item
v-if=
"activeData['inactive-text'] !== undefined"
label=
"关闭提示"
>
<el-input
v-model=
"activeData['inactive-text']"
placeholder=
"请输入关闭提示"
/>
</el-form-item>
<el-form-item
v-if=
"activeData['active-value'] !== undefined"
label=
"开启值"
>
<el-input
:value=
"setDefaultValue(activeData['active-value'])"
placeholder=
"请输入开启值"
@
input=
"onSwitchValueInput($event, 'active-value')"
/>
</el-form-item>
<el-form-item
v-if=
"activeData['inactive-value'] !== undefined"
label=
"关闭值"
>
<el-input
:value=
"setDefaultValue(activeData['inactive-value'])"
placeholder=
"请输入关闭值"
@
input=
"onSwitchValueInput($event, 'inactive-value')"
/>
</el-form-item>
<el-form-item
v-if=
"activeData.type !== undefined && 'el-date-picker' === activeData.tag"
label=
"时间类型"
>
<el-select
v-model=
"activeData.type"
placeholder=
"请选择时间类型"
:style=
"{ width: '100%' }"
@
change=
"dateTypeChange"
>
<el-option
v-for=
"(item, index) in dateOptions"
:key=
"index"
:label=
"item.label"
:value=
"item.value"
/>
</el-select>
</el-form-item>
<el-form-item
v-if=
"activeData.name !== undefined"
label=
"文件字段名"
>
<el-input
v-model=
"activeData.name"
placeholder=
"请输入上传文件字段名"
/>
</el-form-item>
<el-form-item
v-if=
"activeData.accept !== undefined"
label=
"文件类型"
>
<el-select
v-model=
"activeData.accept"
placeholder=
"请选择文件类型"
:style=
"{ width: '100%' }"
clearable
>
<el-option
label=
"图片"
value=
"image/*"
/>
<el-option
label=
"视频"
value=
"video/*"
/>
<el-option
label=
"音频"
value=
"audio/*"
/>
<el-option
label=
"excel"
value=
".xls,.xlsx"
/>
<el-option
label=
"word"
value=
".doc,.docx"
/>
<el-option
label=
"pdf"
value=
".pdf"
/>
<el-option
label=
"txt"
value=
".txt"
/>
</el-select>
</el-form-item>
<el-form-item
v-if=
"activeData.fileSize !== undefined"
label=
"文件大小"
>
<el-input
v-model.number=
"activeData.fileSize"
placeholder=
"请输入文件大小"
>
<el-select
slot=
"append"
v-model=
"activeData.sizeUnit"
:style=
"{ width: '66px' }"
>
<el-option
label=
"KB"
value=
"KB"
/>
<el-option
label=
"MB"
value=
"MB"
/>
<el-option
label=
"GB"
value=
"GB"
/>
</el-select>
</el-input>
</el-form-item>
<el-form-item
v-if=
"activeData.action !== undefined"
label=
"上传地址"
>
<el-input
v-model=
"activeData.action"
placeholder=
"请输入上传地址"
clearable
/>
</el-form-item>
<el-form-item
v-if=
"activeData['list-type'] !== undefined"
label=
"列表类型"
>
<el-radio-group
v-model=
"activeData['list-type']"
size=
"small"
>
<el-radio-button
label=
"text"
>
text
</el-radio-button>
<el-radio-button
label=
"picture"
>
picture
</el-radio-button>
<el-radio-button
label=
"picture-card"
>
picture-card
</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item
v-if=
"activeData.buttonText !== undefined"
v-show=
"'picture-card' !== activeData['list-type']"
label=
"按钮文字"
>
<el-input
v-model=
"activeData.buttonText"
placeholder=
"请输入按钮文字"
/>
</el-form-item>
<el-form-item
v-if=
"activeData['range-separator'] !== undefined"
label=
"分隔符"
>
<el-input
v-model=
"activeData['range-separator']"
placeholder=
"请输入分隔符"
/>
</el-form-item>
<el-form-item
v-if=
"activeData['picker-options'] !== undefined"
label=
"时间段"
>
<el-input
v-model=
"activeData['picker-options'].selectableRange"
placeholder=
"请输入时间段"
/>
</el-form-item>
<el-form-item
v-if=
"activeData.format !== undefined"
label=
"时间格式"
>
<el-input
:value=
"activeData.format"
placeholder=
"请输入时间格式"
@
input=
"setTimeValue($event)"
/>
</el-form-item>
<
template
v-if=
"['el-checkbox-group', 'el-radio-group', 'el-select'].indexOf(activeData.tag) > -1"
>
<el-divider>
选项
</el-divider>
<draggable
:list=
"activeData.options"
:animation=
"340"
group=
"selectItem"
handle=
".option-drag"
>
<div
v-for=
"(item, index) in activeData.options"
:key=
"index"
class=
"select-item"
>
<div
class=
"select-line-icon option-drag"
>
<i
class=
"el-icon-s-operation"
/>
</div>
<el-input
v-model=
"item.label"
placeholder=
"选项名"
size=
"small"
/>
<el-input
placeholder=
"选项值"
size=
"small"
:value=
"item.value"
@
input=
"setOptionValue(item, $event)"
/>
<div
class=
"close-btn select-line-icon"
@
click=
"activeData.options.splice(index, 1)"
>
<i
class=
"el-icon-remove-outline"
/>
</div>
</div>
</draggable>
<div
style=
"margin-left: 20px;"
>
<el-button
style=
"padding-bottom: 0"
icon=
"el-icon-circle-plus-outline"
type=
"text"
@
click=
"addSelectItem"
>
添加选项
</el-button>
</div>
<el-divider
/>
</
template
>
<
template
v-if=
"['el-cascader'].indexOf(activeData.tag) > -1"
>
<el-divider>
选项
</el-divider>
<el-form-item
label=
"数据类型"
>
<el-radio-group
v-model=
"activeData.dataType"
size=
"small"
>
<el-radio-button
label=
"dynamic"
>
动态数据
</el-radio-button>
<el-radio-button
label=
"static"
>
静态数据
</el-radio-button>
</el-radio-group>
</el-form-item>
<template
v-if=
"activeData.dataType === 'dynamic'"
>
<el-form-item
label=
"标签键名"
>
<el-input
v-model=
"activeData.labelKey"
placeholder=
"请输入标签键名"
/>
</el-form-item>
<el-form-item
label=
"值键名"
>
<el-input
v-model=
"activeData.valueKey"
placeholder=
"请输入值键名"
/>
</el-form-item>
<el-form-item
label=
"子级键名"
>
<el-input
v-model=
"activeData.childrenKey"
placeholder=
"请输入子级键名"
/>
</el-form-item>
</
template
>
<el-tree
v-if=
"activeData.dataType === 'static'"
draggable
:data=
"activeData.options"
node-key=
"id"
:expand-on-click-node=
"false"
:render-content=
"renderContent"
/>
<div
v-if=
"activeData.dataType === 'static'"
style=
"margin-left: 20px"
>
<el-button
style=
"padding-bottom: 0"
icon=
"el-icon-circle-plus-outline"
type=
"text"
@
click=
"addTreeItem"
>
添加父级
</el-button>
</div>
<el-divider
/>
</template>
<el-form-item
v-if=
"activeData.optionType !== undefined"
label=
"选项样式"
>
<el-radio-group
v-model=
"activeData.optionType"
>
<el-radio-button
label=
"default"
>
默认
</el-radio-button>
<el-radio-button
label=
"button"
>
按钮
</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item
v-if=
"activeData['active-color'] !== undefined"
label=
"开启颜色"
>
<el-color-picker
v-model=
"activeData['active-color']"
/>
</el-form-item>
<el-form-item
v-if=
"activeData['inactive-color'] !== undefined"
label=
"关闭颜色"
>
<el-color-picker
v-model=
"activeData['inactive-color']"
/>
</el-form-item>
<el-form-item
v-if=
"activeData['allow-half'] !== undefined"
label=
"允许半选"
>
<el-switch
v-model=
"activeData['allow-half']"
/>
</el-form-item>
<el-form-item
v-if=
"activeData['show-text'] !== undefined"
label=
"辅助文字"
>
<el-switch
v-model=
"activeData['show-text']"
@
change=
"rateTextChange"
/>
</el-form-item>
<el-form-item
v-if=
"activeData['show-score'] !== undefined"
label=
"显示分数"
>
<el-switch
v-model=
"activeData['show-score']"
@
change=
"rateScoreChange"
/>
</el-form-item>
<el-form-item
v-if=
"activeData['show-stops'] !== undefined"
label=
"显示间断点"
>
<el-switch
v-model=
"activeData['show-stops']"
/>
</el-form-item>
<el-form-item
v-if=
"activeData.range !== undefined"
label=
"范围选择"
>
<el-switch
v-model=
"activeData.range"
@
change=
"rangeChange"
/>
</el-form-item>
<el-form-item
v-if=
"activeData.border !== undefined && activeData.optionType === 'default'"
label=
"是否带边框"
>
<el-switch
v-model=
"activeData.border"
/>
</el-form-item>
<el-form-item
v-if=
"activeData.tag === 'el-color-picker'"
label=
"颜色格式"
>
<el-select
v-model=
"activeData['color-format']"
placeholder=
"请选择颜色格式"
:style=
"{ width: '100%' }"
@
change=
"colorFormatChange"
>
<el-option
v-for=
"(item, index) in colorFormatOptions"
:key=
"index"
:label=
"item.label"
:value=
"item.value"
/>
</el-select>
</el-form-item>
<el-form-item
v-if=
"activeData.size !== undefined &&
(activeData.optionType === 'button' ||
activeData.border ||
activeData.tag === 'el-color-picker')"
label=
"选项尺寸"
>
<el-radio-group
v-model=
"activeData.size"
>
<el-radio-button
label=
"medium"
>
中等
</el-radio-button>
<el-radio-button
label=
"small"
>
较小
</el-radio-button>
<el-radio-button
label=
"mini"
>
迷你
</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item
v-if=
"activeData['show-word-limit'] !== undefined"
label=
"输入统计"
>
<el-switch
v-model=
"activeData['show-word-limit']"
/>
</el-form-item>
<el-form-item
v-if=
"activeData.tag === 'el-input-number'"
label=
"严格步数"
>
<el-switch
v-model=
"activeData['step-strictly']"
/>
</el-form-item>
<el-form-item
v-if=
"activeData.tag === 'el-cascader'"
label=
"是否多选"
>
<el-switch
v-model=
"activeData.props.props.multiple"
/>
</el-form-item>
<el-form-item
v-if=
"activeData.tag === 'el-cascader'"
label=
"展示全路径"
>
<el-switch
v-model=
"activeData['show-all-levels']"
/>
</el-form-item>
<el-form-item
v-if=
"activeData.tag === 'el-cascader'"
label=
"可否筛选"
>
<el-switch
v-model=
"activeData.filterable"
/>
</el-form-item>
<el-form-item
v-if=
"activeData.clearable !== undefined"
label=
"能否清空"
>
<el-switch
v-model=
"activeData.clearable"
/>
</el-form-item>
<el-form-item
v-if=
"activeData.showTip !== undefined"
label=
"显示提示"
>
<el-switch
v-model=
"activeData.showTip"
/>
</el-form-item>
<el-form-item
v-if=
"activeData.multiple !== undefined"
label=
"多选文件"
>
<el-switch
v-model=
"activeData.multiple"
/>
</el-form-item>
<el-form-item
v-if=
"activeData['auto-upload'] !== undefined"
label=
"自动上传"
>
<el-switch
v-model=
"activeData['auto-upload']"
/>
</el-form-item>
<el-form-item
v-if=
"activeData.readonly !== undefined"
label=
"是否只读"
>
<el-switch
v-model=
"activeData.readonly"
/>
</el-form-item>
<el-form-item
v-if=
"activeData.disabled !== undefined"
label=
"是否禁用"
>
<el-switch
v-model=
"activeData.disabled"
/>
</el-form-item>
<el-form-item
v-if=
"activeData.tag === 'el-select'"
label=
"是否可搜索"
>
<el-switch
v-model=
"activeData.filterable"
/>
</el-form-item>
<el-form-item
v-if=
"activeData.tag === 'el-select'"
label=
"是否多选"
>
<el-switch
v-model=
"activeData.multiple"
@
change=
"multipleChange"
/>
</el-form-item>
<el-form-item
v-if=
"activeData.required !== undefined"
label=
"是否必填"
>
<el-switch
v-model=
"activeData.required"
/>
</el-form-item>
<
template
v-if=
"activeData.layoutTree"
>
<el-divider>
布局结构树
</el-divider>
<el-tree
:data=
"[activeData]"
:props=
"layoutTreeProps"
node-key=
"renderKey"
default-expand-all
draggable
>
<span
slot-scope=
"
{ node, data }">
<span
class=
"node-label"
>
<svg-icon
class=
"node-icon"
:icon-class=
"data.tagIcon"
/>
{{
node
.
label
}}
</span>
</span>
</el-tree>
</
template
>
<
template
v-if=
"activeData.layout === 'colFormItem'"
>
<el-divider>
正则校验
</el-divider>
<div
v-for=
"(item, index) in activeData.regList"
:key=
"index"
class=
"reg-item"
>
<span
class=
"close-btn"
@
click=
"activeData.regList.splice(index, 1)"
>
<i
class=
"el-icon-close"
/>
</span>
<el-form-item
label=
"表达式"
>
<el-input
v-model=
"item.pattern"
placeholder=
"请输入正则"
/>
</el-form-item>
<el-form-item
label=
"错误提示"
style=
"margin-bottom:0"
>
<el-input
v-model=
"item.message"
placeholder=
"请输入错误提示"
/>
</el-form-item>
</div>
<div
style=
"margin-left: 20px"
>
<el-button
icon=
"el-icon-circle-plus-outline"
type=
"text"
@
click=
"addReg"
>
添加规则
</el-button>
</div>
</
template
>
</el-form>
<!-- 表单属性 -->
<el-form
v-show=
"currentTab === 'form'"
size=
"small"
label-width=
"90px"
>
<el-form-item
label=
"表单名"
>
<el-input
v-model=
"formConf.formRef"
placeholder=
"请输入表单名(ref)"
/>
</el-form-item>
<el-form-item
label=
"表单模型"
>
<el-input
v-model=
"formConf.formModel"
placeholder=
"请输入数据模型"
/>
</el-form-item>
<el-form-item
label=
"校验模型"
>
<el-input
v-model=
"formConf.formRules"
placeholder=
"请输入校验模型"
/>
</el-form-item>
<el-form-item
label=
"表单尺寸"
>
<el-radio-group
v-model=
"formConf.size"
>
<el-radio-button
label=
"medium"
>
中等
</el-radio-button>
<el-radio-button
label=
"small"
>
较小
</el-radio-button>
<el-radio-button
label=
"mini"
>
迷你
</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item
label=
"标签对齐"
>
<el-radio-group
v-model=
"formConf.labelPosition"
>
<el-radio-button
label=
"left"
>
左对齐
</el-radio-button>
<el-radio-button
label=
"right"
>
右对齐
</el-radio-button>
<el-radio-button
label=
"top"
>
顶部对齐
</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item
label=
"标签宽度"
>
<el-input-number
v-model=
"formConf.labelWidth"
placeholder=
"标签宽度"
/>
</el-form-item>
<el-form-item
label=
"栅格间隔"
>
<el-input-number
v-model=
"formConf.gutter"
:min=
"0"
placeholder=
"栅格间隔"
/>
</el-form-item>
<el-form-item
label=
"禁用表单"
>
<el-switch
v-model=
"formConf.disabled"
/>
</el-form-item>
<el-form-item
label=
"表单按钮"
>
<el-switch
v-model=
"formConf.formBtns"
/>
</el-form-item>
<el-form-item
label=
"显示未选中组件边框"
>
<el-switch
v-model=
"formConf.unFocusedComponentBorder"
/>
</el-form-item>
</el-form>
</el-scrollbar>
</div>
<treeNode-dialog
:visible.sync=
"dialogVisible"
title=
"添加选项"
@
commit=
"addNode"
/>
<icons-dialog
:visible.sync=
"iconsVisible"
:current=
"activeData[currentIconModel]"
@
select=
"setIcon"
/>
</div>
</template>
<
script
>
import
{
isArray
}
from
'
util
'
import
TreeNodeDialog
from
'
./TreeNodeDialog
'
import
{
isNumberStr
}
from
'
@/utils/index
'
import
IconsDialog
from
'
./IconsDialog
'
import
{
inputComponents
,
selectComponents
,
layoutComponents
}
from
'
@/utils/generator/config
'
const
dateTimeFormat
=
{
date
:
'
yyyy-MM-dd
'
,
week
:
'
yyyy 第 WW 周
'
,
month
:
'
yyyy-MM
'
,
year
:
'
yyyy
'
,
datetime
:
'
yyyy-MM-dd HH:mm:ss
'
,
daterange
:
'
yyyy-MM-dd
'
,
monthrange
:
'
yyyy-MM
'
,
datetimerange
:
'
yyyy-MM-dd HH:mm:ss
'
}
export
default
{
components
:
{
TreeNodeDialog
,
IconsDialog
},
props
:
[
'
showField
'
,
'
activeData
'
,
'
formConf
'
],
data
()
{
return
{
currentTab
:
'
field
'
,
currentNode
:
null
,
dialogVisible
:
false
,
iconsVisible
:
false
,
currentIconModel
:
null
,
dateTypeOptions
:
[
{
label
:
'
日(date)
'
,
value
:
'
date
'
},
{
label
:
'
周(week)
'
,
value
:
'
week
'
},
{
label
:
'
月(month)
'
,
value
:
'
month
'
},
{
label
:
'
年(year)
'
,
value
:
'
year
'
},
{
label
:
'
日期时间(datetime)
'
,
value
:
'
datetime
'
}
],
dateRangeTypeOptions
:
[
{
label
:
'
日期范围(daterange)
'
,
value
:
'
daterange
'
},
{
label
:
'
月范围(monthrange)
'
,
value
:
'
monthrange
'
},
{
label
:
'
日期时间范围(datetimerange)
'
,
value
:
'
datetimerange
'
}
],
colorFormatOptions
:
[
{
label
:
'
hex
'
,
value
:
'
hex
'
},
{
label
:
'
rgb
'
,
value
:
'
rgb
'
},
{
label
:
'
rgba
'
,
value
:
'
rgba
'
},
{
label
:
'
hsv
'
,
value
:
'
hsv
'
},
{
label
:
'
hsl
'
,
value
:
'
hsl
'
}
],
justifyOptions
:
[
{
label
:
'
start
'
,
value
:
'
start
'
},
{
label
:
'
end
'
,
value
:
'
end
'
},
{
label
:
'
center
'
,
value
:
'
center
'
},
{
label
:
'
space-around
'
,
value
:
'
space-around
'
},
{
label
:
'
space-between
'
,
value
:
'
space-between
'
}
],
layoutTreeProps
:
{
label
(
data
,
node
)
{
return
data
.
componentName
||
`
${
data
.
label
}
:
${
data
.
vModel
}
`
}
}
}
},
computed
:
{
documentLink
()
{
return
(
this
.
activeData
.
document
||
'
https://element.eleme.cn/#/zh-CN/component/installation
'
)
},
dateOptions
()
{
if
(
this
.
activeData
.
type
!==
undefined
&&
this
.
activeData
.
tag
===
'
el-date-picker
'
)
{
if
(
this
.
activeData
[
'
start-placeholder
'
]
===
undefined
)
{
return
this
.
dateTypeOptions
}
return
this
.
dateRangeTypeOptions
}
return
[]
},
tagList
()
{
return
[
{
label
:
'
输入型组件
'
,
options
:
inputComponents
},
{
label
:
'
选择型组件
'
,
options
:
selectComponents
}
]
}
},
methods
:
{
addReg
()
{
this
.
activeData
.
regList
.
push
({
pattern
:
''
,
message
:
''
})
},
addSelectItem
()
{
this
.
activeData
.
options
.
push
({
label
:
''
,
value
:
''
})
},
addTreeItem
()
{
++
this
.
idGlobal
this
.
dialogVisible
=
true
this
.
currentNode
=
this
.
activeData
.
options
},
renderContent
(
h
,
{
node
,
data
,
store
})
{
return
(
<
div
class
=
"
custom-tree-node
"
>
<
span
>
{
node
.
label
}
<
/span>
<
span
class
=
"
node-operation
"
>
<
i
on
-
click
=
{()
=>
this
.
append
(
data
)}
class
=
"
el-icon-plus
"
title
=
"
添加
"
><
/i>
<
i
on
-
click
=
{()
=>
this
.
remove
(
node
,
data
)}
class
=
"
el-icon-delete
"
title
=
"
删除
"
><
/i>
<
/span>
<
/div>
)
},
append
(
data
)
{
if
(
!
data
.
children
)
{
this
.
$set
(
data
,
'
children
'
,
[])
}
this
.
dialogVisible
=
true
this
.
currentNode
=
data
.
children
},
remove
(
node
,
data
)
{
const
{
parent
}
=
node
const
children
=
parent
.
data
.
children
||
parent
.
data
const
index
=
children
.
findIndex
(
d
=>
d
.
id
===
data
.
id
)
children
.
splice
(
index
,
1
)
},
addNode
(
data
)
{
this
.
currentNode
.
push
(
data
)
},
setOptionValue
(
item
,
val
)
{
item
.
value
=
isNumberStr
(
val
)
?
+
val
:
val
},
setDefaultValue
(
val
)
{
if
(
Array
.
isArray
(
val
))
{
return
val
.
join
(
'
,
'
)
}
if
([
'
string
'
,
'
number
'
].
indexOf
(
val
)
>
-
1
)
{
return
val
}
if
(
typeof
val
===
'
boolean
'
)
{
return
`
${
val
}
`
}
return
val
},
onDefaultValueInput
(
str
)
{
if
(
isArray
(
this
.
activeData
.
defaultValue
))
{
// 数组
this
.
$set
(
this
.
activeData
,
'
defaultValue
'
,
str
.
split
(
'
,
'
).
map
(
val
=>
(
isNumberStr
(
val
)
?
+
val
:
val
))
)
}
else
if
([
'
true
'
,
'
false
'
].
indexOf
(
str
)
>
-
1
)
{
// 布尔
this
.
$set
(
this
.
activeData
,
'
defaultValue
'
,
JSON
.
parse
(
str
))
}
else
{
// 字符串和数字
this
.
$set
(
this
.
activeData
,
'
defaultValue
'
,
isNumberStr
(
str
)
?
+
str
:
str
)
}
},
onSwitchValueInput
(
val
,
name
)
{
if
([
'
true
'
,
'
false
'
].
indexOf
(
val
)
>
-
1
)
{
this
.
$set
(
this
.
activeData
,
name
,
JSON
.
parse
(
val
))
}
else
{
this
.
$set
(
this
.
activeData
,
name
,
isNumberStr
(
val
)
?
+
val
:
val
)
}
},
setTimeValue
(
val
,
type
)
{
const
valueFormat
=
type
===
'
week
'
?
dateTimeFormat
.
date
:
val
this
.
$set
(
this
.
activeData
,
'
defaultValue
'
,
null
)
this
.
$set
(
this
.
activeData
,
'
value-format
'
,
valueFormat
)
this
.
$set
(
this
.
activeData
,
'
format
'
,
val
)
},
spanChange
(
val
)
{
this
.
formConf
.
span
=
val
},
multipleChange
(
val
)
{
this
.
$set
(
this
.
activeData
,
'
defaultValue
'
,
val
?
[]
:
''
)
},
dateTypeChange
(
val
)
{
this
.
setTimeValue
(
dateTimeFormat
[
val
],
val
)
},
rangeChange
(
val
)
{
this
.
$set
(
this
.
activeData
,
'
defaultValue
'
,
val
?
[
this
.
activeData
.
min
,
this
.
activeData
.
max
]
:
this
.
activeData
.
min
)
},
rateTextChange
(
val
)
{
if
(
val
)
this
.
activeData
[
'
show-score
'
]
=
false
},
rateScoreChange
(
val
)
{
if
(
val
)
this
.
activeData
[
'
show-text
'
]
=
false
},
colorFormatChange
(
val
)
{
this
.
activeData
.
defaultValue
=
null
this
.
activeData
[
'
show-alpha
'
]
=
val
.
indexOf
(
'
a
'
)
>
-
1
this
.
activeData
.
renderKey
=
+
new
Date
()
// 更新renderKey,重新渲染该组件
},
openIconsDialog
(
model
)
{
this
.
iconsVisible
=
true
this
.
currentIconModel
=
model
},
setIcon
(
val
)
{
this
.
activeData
[
this
.
currentIconModel
]
=
val
},
tagChange
(
tagIcon
)
{
let
target
=
inputComponents
.
find
(
item
=>
item
.
tagIcon
===
tagIcon
)
if
(
!
target
)
target
=
selectComponents
.
find
(
item
=>
item
.
tagIcon
===
tagIcon
)
this
.
$emit
(
'
tag-change
'
,
target
)
}
}
}
</
script
>
<
style
lang=
"scss"
scoped
>
.right-board
{
width
:
350px
;
position
:
absolute
;
right
:
0
;
top
:
0
;
padding-top
:
3px
;
.field-box
{
position
:
relative
;
height
:
calc
(
100vh
-
42px
);
box-sizing
:
border-box
;
overflow
:
hidden
;
}
.el-scrollbar
{
height
:
100%
;
}
}
.select-item
{
display
:
flex
;
border
:
1px
dashed
#fff
;
box-sizing
:
border-box
;
&
.close-btn
{
cursor
:
pointer
;
color
:
#f56c6c
;
}
&
.el-input
+
.el-input
{
margin-left
:
4px
;
}
}
.select-item
+
.select-item
{
margin-top
:
4px
;
}
.select-item.sortable-chosen
{
border
:
1px
dashed
#409eff
;
}
.select-line-icon
{
line-height
:
32px
;
font-size
:
22px
;
padding
:
0
4px
;
color
:
#777
;
}
.option-drag
{
cursor
:
move
;
}
.time-range
{
.el-date-editor
{
width
:
227px
;
}
::v-deep
.el-icon-time
{
display
:
none
;
}
}
.document-link
{
position
:
absolute
;
display
:
block
;
width
:
26px
;
height
:
26px
;
top
:
0
;
left
:
0
;
cursor
:
pointer
;
background
:
#409eff
;
z-index
:
1
;
border-radius
:
0
0
6px
0
;
text-align
:
center
;
line-height
:
26px
;
color
:
#fff
;
font-size
:
18px
;
}
.node-label
{
font-size
:
14px
;
}
.node-icon
{
color
:
#bebfc3
;
}
</
style
>
ruoyi-ui/src/views/tool/build/TreeNodeDialog.vue
0 → 100644
View file @
cb0a4b78
<
template
>
<div>
<el-dialog
v-bind=
"$attrs"
:close-on-click-modal=
"false"
:modal-append-to-body=
"false"
v-on=
"$listeners"
@
open=
"onOpen"
@
close=
"onClose"
>
<el-row
:gutter=
"0"
>
<el-form
ref=
"elForm"
:model=
"formData"
:rules=
"rules"
size=
"small"
label-width=
"100px"
>
<el-col
:span=
"24"
>
<el-form-item
label=
"选项名"
prop=
"label"
>
<el-input
v-model=
"formData.label"
placeholder=
"请输入选项名"
clearable
/>
</el-form-item>
</el-col>
<el-col
:span=
"24"
>
<el-form-item
label=
"选项值"
prop=
"value"
>
<el-input
v-model=
"formData.value"
placeholder=
"请输入选项值"
clearable
>
<el-select
slot=
"append"
v-model=
"dataType"
:style=
"
{width: '100px'}"
>
<el-option
v-for=
"(item, index) in dataTypeOptions"
:key=
"index"
:label=
"item.label"
:value=
"item.value"
:disabled=
"item.disabled"
/>
</el-select>
</el-input>
</el-form-item>
</el-col>
</el-form>
</el-row>
<div
slot=
"footer"
>
<el-button
type=
"primary"
@
click=
"handelConfirm"
>
确定
</el-button>
<el-button
@
click=
"close"
>
取消
</el-button>
</div>
</el-dialog>
</div>
</
template
>
<
script
>
import
{
isNumberStr
}
from
'
@/utils/index
'
export
default
{
components
:
{},
inheritAttrs
:
false
,
props
:
[],
data
()
{
return
{
id
:
100
,
formData
:
{
label
:
undefined
,
value
:
undefined
},
rules
:
{
label
:
[
{
required
:
true
,
message
:
'
请输入选项名
'
,
trigger
:
'
blur
'
}
],
value
:
[
{
required
:
true
,
message
:
'
请输入选项值
'
,
trigger
:
'
blur
'
}
]
},
dataType
:
'
string
'
,
dataTypeOptions
:
[
{
label
:
'
字符串
'
,
value
:
'
string
'
},
{
label
:
'
数字
'
,
value
:
'
number
'
}
]
}
},
computed
:
{},
watch
:
{
// eslint-disable-next-line func-names
'
formData.value
'
:
function
(
val
)
{
this
.
dataType
=
isNumberStr
(
val
)
?
'
number
'
:
'
string
'
}
},
created
()
{},
mounted
()
{},
methods
:
{
onOpen
()
{
this
.
formData
=
{
label
:
undefined
,
value
:
undefined
}
},
onClose
()
{},
close
()
{
this
.
$emit
(
'
update:visible
'
,
false
)
},
handelConfirm
()
{
this
.
$refs
.
elForm
.
validate
(
valid
=>
{
if
(
!
valid
)
return
if
(
this
.
dataType
===
'
number
'
)
{
this
.
formData
.
value
=
parseFloat
(
this
.
formData
.
value
)
}
this
.
formData
.
id
=
this
.
id
++
this
.
$emit
(
'
commit
'
,
this
.
formData
)
this
.
close
()
})
}
}
}
</
script
>
ruoyi-ui/src/views/tool/build/index.vue
View file @
cb0a4b78
<
template
>
<div
class=
"app-container"
>
构建工具
<div
class=
"container"
>
<div
class=
"left-board"
>
<div
class=
"logo-wrapper"
>
<div
class=
"logo"
>
<img
:src=
"logo"
alt=
"logo"
>
Form Generator
</div>
</div>
<el-scrollbar
class=
"left-scrollbar"
>
<div
class=
"components-list"
>
<div
class=
"components-title"
>
<svg-icon
icon-class=
"component"
/>
输入型组件
</div>
<draggable
class=
"components-draggable"
:list=
"inputComponents"
:group=
"
{ name: 'componentsGroup', pull: 'clone', put: false }"
:clone="cloneComponent"
draggable=".components-item"
:sort="false"
@end="onEnd"
>
<div
v-for=
"(element, index) in inputComponents"
:key=
"index"
class=
"components-item"
@
click=
"addComponent(element)"
>
<div
class=
"components-body"
>
<svg-icon
:icon-class=
"element.tagIcon"
/>
{{
element
.
label
}}
</div>
</div>
</draggable>
<div
class=
"components-title"
>
<svg-icon
icon-class=
"component"
/>
选择型组件
</div>
<draggable
class=
"components-draggable"
:list=
"selectComponents"
:group=
"
{ name: 'componentsGroup', pull: 'clone', put: false }"
:clone="cloneComponent"
draggable=".components-item"
:sort="false"
@end="onEnd"
>
<div
v-for=
"(element, index) in selectComponents"
:key=
"index"
class=
"components-item"
@
click=
"addComponent(element)"
>
<div
class=
"components-body"
>
<svg-icon
:icon-class=
"element.tagIcon"
/>
{{
element
.
label
}}
</div>
</div>
</draggable>
<div
class=
"components-title"
>
<svg-icon
icon-class=
"component"
/>
布局型组件
</div>
<draggable
class=
"components-draggable"
:list=
"layoutComponents"
:group=
"
{ name: 'componentsGroup', pull: 'clone', put: false }" :clone="cloneComponent"
draggable=".components-item" :sort="false" @end="onEnd"
>
<div
v-for=
"(element, index) in layoutComponents"
:key=
"index"
class=
"components-item"
@
click=
"addComponent(element)"
>
<div
class=
"components-body"
>
<svg-icon
:icon-class=
"element.tagIcon"
/>
{{
element
.
label
}}
</div>
</div>
</draggable>
</div>
</el-scrollbar>
</div>
<div
class=
"center-board"
>
<div
class=
"action-bar"
>
<el-button
icon=
"el-icon-download"
type=
"text"
@
click=
"download"
>
导出vue文件
</el-button>
<el-button
class=
"copy-btn-main"
icon=
"el-icon-document-copy"
type=
"text"
@
click=
"copy"
>
复制代码
</el-button>
<el-button
class=
"delete-btn"
icon=
"el-icon-delete"
type=
"text"
@
click=
"empty"
>
清空
</el-button>
</div>
<el-scrollbar
class=
"center-scrollbar"
>
<el-row
class=
"center-board-row"
:gutter=
"formConf.gutter"
>
<el-form
:size=
"formConf.size"
:label-position=
"formConf.labelPosition"
:disabled=
"formConf.disabled"
:label-width=
"formConf.labelWidth + 'px'"
>
<draggable
class=
"drawing-board"
:list=
"drawingList"
:animation=
"340"
group=
"componentsGroup"
>
<draggable-item
v-for=
"(element, index) in drawingList"
:key=
"element.renderKey"
:drawing-list=
"drawingList"
:element=
"element"
:index=
"index"
:active-id=
"activeId"
:form-conf=
"formConf"
@
activeItem=
"activeFormItem"
@
copyItem=
"drawingItemCopy"
@
deleteItem=
"drawingItemDelete"
/>
</draggable>
<div
v-show=
"!drawingList.length"
class=
"empty-info"
>
从左侧拖入或点选组件进行表单设计
</div>
</el-form>
</el-row>
</el-scrollbar>
</div>
<right-panel
:active-data=
"activeData"
:form-conf=
"formConf"
:show-field=
"!!drawingList.length"
@
tag-change=
"tagChange"
/>
<code-type-dialog
:visible.sync=
"dialogVisible"
title=
"选择生成类型"
:show-file-name=
"showFileName"
@
confirm=
"generate"
/>
<input
id=
"copyNode"
type=
"hidden"
>
</div>
</
template
>
\ No newline at end of file
</
template
>
<
script
>
import
draggable
from
'
vuedraggable
'
import
{
saveAs
}
from
'
file-saver
'
import
beautifier
from
'
js-beautify
'
import
ClipboardJS
from
'
clipboard
'
import
render
from
'
@/utils/generator/render
'
import
RightPanel
from
'
./RightPanel
'
import
{
inputComponents
,
selectComponents
,
layoutComponents
,
formConf
}
from
'
@/utils/generator/config
'
import
{
exportDefault
,
beautifierConf
,
isNumberStr
,
titleCase
}
from
'
@/utils/index
'
import
{
makeUpHtml
,
vueTemplate
,
vueScript
,
cssStyle
}
from
'
@/utils/generator/html
'
import
{
makeUpJs
}
from
'
@/utils/generator/js
'
import
{
makeUpCss
}
from
'
@/utils/generator/css
'
import
drawingDefalut
from
'
@/utils/generator/drawingDefalut
'
import
logo
from
'
@/assets/logo/logo.png
'
import
CodeTypeDialog
from
'
./CodeTypeDialog
'
import
DraggableItem
from
'
./DraggableItem
'
const
emptyActiveData
=
{
style
:
{},
autosize
:
{}
}
let
oldActiveId
let
tempActiveData
export
default
{
components
:
{
draggable
,
render
,
RightPanel
,
CodeTypeDialog
,
DraggableItem
},
data
()
{
return
{
logo
,
idGlobal
:
100
,
formConf
,
inputComponents
,
selectComponents
,
layoutComponents
,
labelWidth
:
100
,
drawingList
:
drawingDefalut
,
drawingData
:
{},
activeId
:
drawingDefalut
[
0
].
formId
,
drawerVisible
:
false
,
formData
:
{},
dialogVisible
:
false
,
generateConf
:
null
,
showFileName
:
false
,
activeData
:
drawingDefalut
[
0
]
}
},
computed
:
{
},
watch
:
{
// eslint-disable-next-line func-names
'
activeData.label
'
:
function
(
val
,
oldVal
)
{
if
(
this
.
activeData
.
placeholder
===
undefined
||
!
this
.
activeData
.
tag
||
oldActiveId
!==
this
.
activeId
)
{
return
}
this
.
activeData
.
placeholder
=
this
.
activeData
.
placeholder
.
replace
(
oldVal
,
''
)
+
val
},
activeId
:
{
handler
(
val
)
{
oldActiveId
=
val
},
immediate
:
true
}
},
mounted
()
{
const
clipboard
=
new
ClipboardJS
(
'
#copyNode
'
,
{
text
:
trigger
=>
{
const
codeStr
=
this
.
generateCode
()
this
.
$notify
({
title
:
'
成功
'
,
message
:
'
代码已复制到剪切板,可粘贴。
'
,
type
:
'
success
'
})
return
codeStr
}
})
clipboard
.
on
(
'
error
'
,
e
=>
{
this
.
$message
.
error
(
'
代码复制失败
'
)
})
},
methods
:
{
activeFormItem
(
element
)
{
this
.
activeData
=
element
this
.
activeId
=
element
.
formId
},
onEnd
(
obj
,
a
)
{
if
(
obj
.
from
!==
obj
.
to
)
{
this
.
activeData
=
tempActiveData
this
.
activeId
=
this
.
idGlobal
}
},
addComponent
(
item
)
{
const
clone
=
this
.
cloneComponent
(
item
)
this
.
drawingList
.
push
(
clone
)
this
.
activeFormItem
(
clone
)
},
cloneComponent
(
origin
)
{
const
clone
=
JSON
.
parse
(
JSON
.
stringify
(
origin
))
clone
.
formId
=
++
this
.
idGlobal
clone
.
span
=
formConf
.
span
clone
.
renderKey
=
+
new
Date
()
// 改变renderKey后可以实现强制更新组件
if
(
!
clone
.
layout
)
clone
.
layout
=
'
colFormItem
'
if
(
clone
.
layout
===
'
colFormItem
'
)
{
clone
.
vModel
=
`field
${
this
.
idGlobal
}
`
clone
.
placeholder
!==
undefined
&&
(
clone
.
placeholder
+=
clone
.
label
)
tempActiveData
=
clone
}
else
if
(
clone
.
layout
===
'
rowFormItem
'
)
{
delete
clone
.
label
clone
.
componentName
=
`row
${
this
.
idGlobal
}
`
clone
.
gutter
=
this
.
formConf
.
gutter
tempActiveData
=
clone
}
return
tempActiveData
},
AssembleFormData
()
{
this
.
formData
=
{
fields
:
JSON
.
parse
(
JSON
.
stringify
(
this
.
drawingList
)),
...
this
.
formConf
}
},
generate
(
data
)
{
const
func
=
this
[
`exec
${
titleCase
(
this
.
operationType
)}
`
]
this
.
generateConf
=
data
func
&&
func
(
data
)
},
execRun
(
data
)
{
this
.
AssembleFormData
()
this
.
drawerVisible
=
true
},
execDownload
(
data
)
{
const
codeStr
=
this
.
generateCode
()
const
blob
=
new
Blob
([
codeStr
],
{
type
:
'
text/plain;charset=utf-8
'
})
saveAs
(
blob
,
data
.
fileName
)
},
execCopy
(
data
)
{
document
.
getElementById
(
'
copyNode
'
).
click
()
},
empty
()
{
this
.
$confirm
(
'
确定要清空所有组件吗?
'
,
'
提示
'
,
{
type
:
'
warning
'
}).
then
(
()
=>
{
this
.
drawingList
=
[]
}
)
},
drawingItemCopy
(
item
,
parent
)
{
let
clone
=
JSON
.
parse
(
JSON
.
stringify
(
item
))
clone
=
this
.
createIdAndKey
(
clone
)
parent
.
push
(
clone
)
this
.
activeFormItem
(
clone
)
},
createIdAndKey
(
item
)
{
item
.
formId
=
++
this
.
idGlobal
item
.
renderKey
=
+
new
Date
()
if
(
item
.
layout
===
'
colFormItem
'
)
{
item
.
vModel
=
`field
${
this
.
idGlobal
}
`
}
else
if
(
item
.
layout
===
'
rowFormItem
'
)
{
item
.
componentName
=
`row
${
this
.
idGlobal
}
`
}
if
(
Array
.
isArray
(
item
.
children
))
{
item
.
children
=
item
.
children
.
map
(
childItem
=>
this
.
createIdAndKey
(
childItem
))
}
return
item
},
drawingItemDelete
(
index
,
parent
)
{
parent
.
splice
(
index
,
1
)
this
.
$nextTick
(()
=>
{
const
len
=
this
.
drawingList
.
length
if
(
len
)
{
this
.
activeFormItem
(
this
.
drawingList
[
len
-
1
])
}
})
},
generateCode
()
{
const
{
type
}
=
this
.
generateConf
this
.
AssembleFormData
()
const
script
=
vueScript
(
makeUpJs
(
this
.
formData
,
type
))
const
html
=
vueTemplate
(
makeUpHtml
(
this
.
formData
,
type
))
const
css
=
cssStyle
(
makeUpCss
(
this
.
formData
))
return
beautifier
.
html
(
html
+
script
+
css
,
beautifierConf
.
html
)
},
download
()
{
this
.
dialogVisible
=
true
this
.
showFileName
=
true
this
.
operationType
=
'
download
'
},
run
()
{
this
.
dialogVisible
=
true
this
.
showFileName
=
false
this
.
operationType
=
'
run
'
},
copy
()
{
this
.
dialogVisible
=
true
this
.
showFileName
=
false
this
.
operationType
=
'
copy
'
},
tagChange
(
newTag
)
{
newTag
=
this
.
cloneComponent
(
newTag
)
newTag
.
vModel
=
this
.
activeData
.
vModel
newTag
.
formId
=
this
.
activeId
newTag
.
span
=
this
.
activeData
.
span
delete
this
.
activeData
.
tag
delete
this
.
activeData
.
tagIcon
delete
this
.
activeData
.
document
Object
.
keys
(
newTag
).
forEach
(
key
=>
{
if
(
this
.
activeData
[
key
]
!==
undefined
&&
typeof
this
.
activeData
[
key
]
===
typeof
newTag
[
key
])
{
newTag
[
key
]
=
this
.
activeData
[
key
]
}
})
this
.
activeData
=
newTag
this
.
updateDrawingList
(
newTag
,
this
.
drawingList
)
},
updateDrawingList
(
newTag
,
list
)
{
const
index
=
list
.
findIndex
(
item
=>
item
.
formId
===
this
.
activeId
)
if
(
index
>
-
1
)
{
list
.
splice
(
index
,
1
,
newTag
)
}
else
{
list
.
forEach
(
item
=>
{
if
(
Array
.
isArray
(
item
.
children
))
this
.
updateDrawingList
(
newTag
,
item
.
children
)
})
}
}
}
}
</
script
>
<
style
lang=
'scss'
>
body
,
html
{
margin
:
0
;
padding
:
0
;
background
:
#fff
;
-moz-osx-font-smoothing
:
grayscale
;
-webkit-font-smoothing
:
antialiased
;
text-rendering
:
optimizeLegibility
;
font-family
:
-
apple-system
,
BlinkMacSystemFont
,
Segoe
UI
,
Helvetica
,
Arial
,
sans-serif
,
Apple
Color
Emoji
,
Segoe
UI
Emoji
;
}
input
,
textarea
{
font-family
:
-
apple-system
,
BlinkMacSystemFont
,
Segoe
UI
,
Helvetica
,
Arial
,
sans-serif
,
Apple
Color
Emoji
,
Segoe
UI
Emoji
;
}
.editor-tabs
{
background
:
#121315
;
.el-tabs__header
{
margin
:
0
;
border-bottom-color
:
#121315
;
.el-tabs__nav
{
border-color
:
#121315
;
}
}
.el-tabs__item
{
height
:
32px
;
line-height
:
32px
;
color
:
#888a8e
;
border-left
:
1px
solid
#121315
!
important
;
background
:
#363636
;
margin-right
:
5px
;
user-select
:
none
;
}
.el-tabs__item.is-active
{
background
:
#1e1e1e
;
border-bottom-color
:
#1e1e1e
!
important
;
color
:
#fff
;
}
.el-icon-edit
{
color
:
#f1fa8c
;
}
.el-icon-document
{
color
:
#a95812
;
}
}
// home
.right-scrollbar
{
.el-scrollbar__view
{
padding
:
12px
18px
15px
15px
;
}
}
.el-scrollbar__wrap
{
box-sizing
:
border-box
;
overflow-x
:
hidden
!
important
;
margin-bottom
:
0
!
important
;
}
.center-tabs
{
.el-tabs__header
{
margin-bottom
:
0
!
important
;
}
.el-tabs__item
{
width
:
50%
;
text-align
:
center
;
}
.el-tabs__nav
{
width
:
100%
;
}
}
.reg-item
{
padding
:
12px
6px
;
background
:
#f8f8f8
;
position
:
relative
;
border-radius
:
4px
;
.close-btn
{
position
:
absolute
;
right
:
-6px
;
top
:
-6px
;
display
:
block
;
width
:
16px
;
height
:
16px
;
line-height
:
16px
;
background
:
rgba
(
0
,
0
,
0
,
0
.2
);
border-radius
:
50%
;
color
:
#fff
;
text-align
:
center
;
z-index
:
1
;
cursor
:
pointer
;
font-size
:
12px
;
&
:hover
{
background
:
rgba
(
210
,
23
,
23
,
0
.5
)
}
}
&
+
.reg-item
{
margin-top
:
18px
;
}
}
.action-bar
{
&
.el-button
+
.el-button
{
margin-left
:
15px
;
}
&
i
{
font-size
:
20px
;
vertical-align
:
middle
;
position
:
relative
;
top
:
-1px
;
}
}
.custom-tree-node
{
width
:
100%
;
font-size
:
14px
;
.node-operation
{
float
:
right
;
}
i
[
class
*=
"el-icon"
]
+
i
[
class
*=
"el-icon"
]
{
margin-left
:
6px
;
}
.el-icon-plus
{
color
:
#409EFF
;
}
.el-icon-delete
{
color
:
#157a0c
;
}
}
.el-scrollbar__view
{
overflow-x
:
hidden
;
}
.el-rate
{
display
:
inline-block
;
vertical-align
:
text-top
;
}
.el-upload__tip
{
line-height
:
1
.2
;
}
$selectedColor
:
#f6f7ff
;
$lighterBlue
:
#409EFF
;
.container
{
position
:
relative
;
width
:
100%
;
height
:
100%
;
}
.components-list
{
padding
:
8px
;
box-sizing
:
border-box
;
height
:
100%
;
.components-item
{
display
:
inline-block
;
width
:
48%
;
margin
:
1%
;
transition
:
transform
0ms
!
important
;
}
}
.components-draggable
{
padding-bottom
:
20px
;
}
.components-title
{
font-size
:
14px
;
color
:
#222
;
margin
:
6px
2px
;
.svg-icon
{
color
:
#666
;
font-size
:
18px
;
}
}
.components-body
{
padding
:
8px
10px
;
background
:
$selectedColor
;
font-size
:
12px
;
cursor
:
move
;
border
:
1px
dashed
$selectedColor
;
border-radius
:
3px
;
.svg-icon
{
color
:
#777
;
font-size
:
15px
;
}
&
:hover
{
border
:
1px
dashed
#787be8
;
color
:
#787be8
;
.svg-icon
{
color
:
#787be8
;
}
}
}
.left-board
{
width
:
260px
;
position
:
absolute
;
left
:
0
;
top
:
0
;
height
:
100vh
;
}
.left-scrollbar
{
height
:
calc
(
100vh
-
42px
);
overflow
:
hidden
;
}
.center-scrollbar
{
height
:
calc
(
100vh
-
42px
);
overflow
:
hidden
;
border-left
:
1px
solid
#f1e8e8
;
border-right
:
1px
solid
#f1e8e8
;
box-sizing
:
border-box
;
}
.center-board
{
height
:
100vh
;
width
:
auto
;
margin
:
0
350px
0
260px
;
box-sizing
:
border-box
;
}
.empty-info
{
position
:
absolute
;
top
:
46%
;
left
:
0
;
right
:
0
;
text-align
:
center
;
font-size
:
18px
;
color
:
#ccb1ea
;
letter-spacing
:
4px
;
}
.action-bar
{
position
:
relative
;
height
:
42px
;
text-align
:
right
;
padding
:
0
15px
;
box-sizing
:
border-box
;;
border
:
1px
solid
#f1e8e8
;
border-top
:
none
;
border-left
:
none
;
.delete-btn
{
color
:
#F56C6C
;
}
}
.logo-wrapper
{
position
:
relative
;
height
:
42px
;
background
:
#fff
;
border-bottom
:
1px
solid
#f1e8e8
;
box-sizing
:
border-box
;
}
.logo
{
position
:
absolute
;
left
:
12px
;
top
:
6px
;
line-height
:
30px
;
color
:
#00afff
;
font-weight
:
600
;
font-size
:
17px
;
white-space
:
nowrap
;
>
img
{
width
:
30px
;
height
:
30px
;
vertical-align
:
top
;
}
.github
{
display
:
inline-block
;
vertical-align
:
sub
;
margin-left
:
15px
;
>
img
{
height
:
22px
;
}
}
}
.center-board-row
{
padding
:
12px
12px
15px
12px
;
box-sizing
:
border-box
;
&
>
.el-form
{
// 69 = 12+15+42
height
:
calc
(
100vh
-
69px
);
}
}
.drawing-board
{
height
:
100%
;
position
:
relative
;
.components-body
{
padding
:
0
;
margin
:
0
;
font-size
:
0
;
}
.sortable-ghost
{
position
:
relative
;
display
:
block
;
overflow
:
hidden
;
&
::before
{
content
:
" "
;
position
:
absolute
;
left
:
0
;
right
:
0
;
top
:
0
;
height
:
3px
;
background
:
rgb
(
89
,
89
,
223
);
z-index
:
2
;
}
}
.components-item.sortable-ghost
{
width
:
100%
;
height
:
60px
;
background-color
:
$selectedColor
;
}
.active-from-item
{
&
>
.el-form-item
{
background
:
$selectedColor
;
border-radius
:
6px
;
}
&
>
.drawing-item-copy
,
&
>
.drawing-item-delete
{
display
:
initial
;
}
&
>
.component-name
{
color
:
$lighterBlue
;
}
}
.el-form-item
{
margin-bottom
:
15px
;
}
}
.drawing-item
{
position
:
relative
;
cursor
:
move
;
&
.unfocus-bordered
:not
(
.activeFromItem
)
>
div
:first-child
{
border
:
1px
dashed
#ccc
;
}
.el-form-item
{
padding
:
12px
10px
;
}
}
.drawing-row-item
{
position
:
relative
;
cursor
:
move
;
box-sizing
:
border-box
;
border
:
1px
dashed
#ccc
;
border-radius
:
3px
;
padding
:
0
2px
;
margin-bottom
:
15px
;
.drawing-row-item
{
margin-bottom
:
2px
;
}
.el-col
{
margin-top
:
22px
;
}
.el-form-item
{
margin-bottom
:
0
;
}
.drag-wrapper
{
min-height
:
80px
;
}
&
.active-from-item
{
border
:
1px
dashed
$lighterBlue
;
}
.component-name
{
position
:
absolute
;
top
:
0
;
left
:
0
;
font-size
:
12px
;
color
:
#bbb
;
display
:
inline-block
;
padding
:
0
6px
;
}
}
.drawing-item
,
.drawing-row-item
{
&
:hover
{
&
>
.el-form-item
{
background
:
$selectedColor
;
border-radius
:
6px
;
}
&
>
.drawing-item-copy
,
&
>
.drawing-item-delete
{
display
:
initial
;
}
}
&
>
.drawing-item-copy
,
&
>
.drawing-item-delete
{
display
:
none
;
position
:
absolute
;
top
:
-10px
;
width
:
22px
;
height
:
22px
;
line-height
:
22px
;
text-align
:
center
;
border-radius
:
50%
;
font-size
:
12px
;
border
:
1px
solid
;
cursor
:
pointer
;
z-index
:
1
;
}
&
>
.drawing-item-copy
{
right
:
56px
;
border-color
:
$lighterBlue
;
color
:
$lighterBlue
;
background
:
#fff
;
&
:hover
{
background
:
$lighterBlue
;
color
:
#fff
;
}
}
&
>
.drawing-item-delete
{
right
:
24px
;
border-color
:
#F56C6C
;
color
:
#F56C6C
;
background
:
#fff
;
&
:hover
{
background
:
#F56C6C
;
color
:
#fff
;
}
}
}
</
style
>
ruoyi-ui/src/views/tool/gen/genInfoForm.vue
View file @
cb0a4b78
...
...
@@ -6,7 +6,7 @@
<span
slot=
"label"
>
生成模板
</span>
<el-select
v-model=
"info.tplCategory"
>
<el-option
label=
"单表(增删改查)"
value=
"crud"
/>
<el-option
label=
"树表(增删改查)"
value=
"tree"
disabled
/>
<el-option
label=
"树表(增删改查)"
value=
"tree"
/>
</el-select>
</el-form-item>
</el-col>
...
...
ruoyi/pom.xml
View file @
cb0a4b78
...
...
@@ -5,7 +5,7 @@
<groupId>
com.ruoyi
</groupId>
<artifactId>
ruoyi
</artifactId>
<version>
2.
0
.0
</version>
<version>
2.
1
.0
</version>
<packaging>
jar
</packaging>
<name>
ruoyi
</name>
...
...
@@ -43,14 +43,6 @@
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter
</artifactId>
<!--
<exclusions>
<exclusion>
<artifactId>spring-boot-starter-tomcat</artifactId>
<groupId>org.springframework.boot</groupId>
</exclusion>
</exclusions>
-->
</dependency>
<!-- SpringBoot 测试 -->
...
...
ruoyi/src/main/java/com/ruoyi/common/constant/GenConstants.java
View file @
cb0a4b78
...
...
@@ -48,7 +48,7 @@ public class GenConstants
public
static
final
String
[]
BASE_ENTITY
=
{
"createBy"
,
"createTime"
,
"updateBy"
,
"updateTime"
,
"remark"
};
/** Tree基类字段 */
public
static
final
String
[]
TREE_ENTITY
=
{
"parentName"
,
"parentId"
,
"orderNum"
,
"ancestors"
};
public
static
final
String
[]
TREE_ENTITY
=
{
"parentName"
,
"parentId"
,
"orderNum"
,
"ancestors"
,
"children"
};
/** 文本框 */
public
static
final
String
HTML_INPUT
=
"input"
;
...
...
ruoyi/src/main/java/com/ruoyi/common/utils/html/EscapeUtil.java
View file @
cb0a4b78
...
...
@@ -144,7 +144,7 @@ public class EscapeUtil
public
static
void
main
(
String
[]
args
)
{
String
html
=
"
<script>alert(1);</script>
"
;
String
html
=
"
alert('11111');
"
;
System
.
out
.
println
(
EscapeUtil
.
clean
(
html
));
System
.
out
.
println
(
EscapeUtil
.
escape
(
html
));
System
.
out
.
println
(
EscapeUtil
.
unescape
(
html
));
...
...
ruoyi/src/main/java/com/ruoyi/framework/web/domain/TreeEntity.java
0 → 100644
View file @
cb0a4b78
package
com.ruoyi.framework.web.domain
;
import
java.util.ArrayList
;
import
java.util.List
;
/**
* Tree基类
*
* @author ruoyi
*/
public
class
TreeEntity
extends
BaseEntity
{
private
static
final
long
serialVersionUID
=
1L
;
/** 父菜单名称 */
private
String
parentName
;
/** 父菜单ID */
private
Long
parentId
;
/** 显示顺序 */
private
Integer
orderNum
;
/** 祖级列表 */
private
String
ancestors
;
/** 子部门 */
private
List
<?>
children
=
new
ArrayList
<>();
public
String
getParentName
()
{
return
parentName
;
}
public
void
setParentName
(
String
parentName
)
{
this
.
parentName
=
parentName
;
}
public
Long
getParentId
()
{
return
parentId
;
}
public
void
setParentId
(
Long
parentId
)
{
this
.
parentId
=
parentId
;
}
public
Integer
getOrderNum
()
{
return
orderNum
;
}
public
void
setOrderNum
(
Integer
orderNum
)
{
this
.
orderNum
=
orderNum
;
}
public
String
getAncestors
()
{
return
ancestors
;
}
public
void
setAncestors
(
String
ancestors
)
{
this
.
ancestors
=
ancestors
;
}
public
List
<?>
getChildren
()
{
return
children
;
}
public
void
setChildren
(
List
<?>
children
)
{
this
.
children
=
children
;
}
}
ruoyi/src/main/java/com/ruoyi/project/system/controller/SysDeptController.java
View file @
cb0a4b78
...
...
@@ -41,7 +41,7 @@ public class SysDeptController extends BaseController
public
AjaxResult
list
(
SysDept
dept
)
{
List
<
SysDept
>
depts
=
deptService
.
selectDeptList
(
dept
);
return
AjaxResult
.
success
(
dept
Service
.
buildDeptTree
(
depts
)
);
return
AjaxResult
.
success
(
dept
s
);
}
/**
...
...
ruoyi/src/main/java/com/ruoyi/project/system/controller/SysMenuController.java
View file @
cb0a4b78
...
...
@@ -49,7 +49,7 @@ public class SysMenuController extends BaseController
LoginUser
loginUser
=
tokenService
.
getLoginUser
(
ServletUtils
.
getRequest
());
Long
userId
=
loginUser
.
getUser
().
getUserId
();
List
<
SysMenu
>
menus
=
menuService
.
selectMenuList
(
menu
,
userId
);
return
AjaxResult
.
success
(
menu
Service
.
buildMenuTree
(
menus
)
);
return
AjaxResult
.
success
(
menu
s
);
}
/**
...
...
ruoyi/src/main/java/com/ruoyi/project/tool/gen/controller/GenController.java
View file @
cb0a4b78
...
...
@@ -37,7 +37,6 @@ import com.ruoyi.project.tool.gen.service.IGenTableService;
@RequestMapping
(
"/tool/gen"
)
public
class
GenController
extends
BaseController
{
@Autowired
private
IGenTableService
genTableService
;
...
...
ruoyi/src/main/java/com/ruoyi/project/tool/gen/domain/GenTable.java
View file @
cb0a4b78
...
...
@@ -3,6 +3,7 @@ package com.ruoyi.project.tool.gen.domain;
import
java.util.List
;
import
javax.validation.Valid
;
import
javax.validation.constraints.NotBlank
;
import
org.apache.commons.lang3.ArrayUtils
;
import
com.ruoyi.common.constant.GenConstants
;
import
com.ruoyi.common.utils.StringUtils
;
import
com.ruoyi.framework.web.domain.BaseEntity
;
...
...
@@ -262,7 +263,8 @@ public class GenTable extends BaseEntity
{
if
(
isTree
(
tplCategory
))
{
StringUtils
.
equalsAnyIgnoreCase
(
javaField
,
GenConstants
.
TREE_ENTITY
);
return
StringUtils
.
equalsAnyIgnoreCase
(
javaField
,
ArrayUtils
.
addAll
(
GenConstants
.
TREE_ENTITY
,
GenConstants
.
BASE_ENTITY
));
}
return
StringUtils
.
equalsAnyIgnoreCase
(
javaField
,
GenConstants
.
BASE_ENTITY
);
}
...
...
ruoyi/src/main/java/com/ruoyi/project/tool/gen/util/VelocityUtils.java
View file @
cb0a4b78
...
...
@@ -95,7 +95,14 @@ public class VelocityUtils
templates
.
add
(
"vm/xml/mapper.xml.vm"
);
templates
.
add
(
"vm/sql/sql.vm"
);
templates
.
add
(
"vm/js/api.js.vm"
);
templates
.
add
(
"vm/vue/index.vue.vm"
);
if
(
GenConstants
.
TPL_CRUD
.
equals
(
tplCategory
))
{
templates
.
add
(
"vm/vue/index.vue.vm"
);
}
else
if
(
GenConstants
.
TPL_TREE
.
equals
(
tplCategory
))
{
templates
.
add
(
"vm/vue/index-tree.vue.vm"
);
}
return
templates
;
}
...
...
@@ -147,11 +154,15 @@ public class VelocityUtils
{
fileName
=
businessName
+
"Menu.sql"
;
}
else
if
(
template
.
contains
(
"js.vm"
))
else
if
(
template
.
contains
(
"
api.
js.vm"
))
{
fileName
=
StringUtils
.
format
(
"{}/api/{}/{}.js"
,
vuePath
,
moduleName
,
businessName
);
}
else
if
(
template
.
contains
(
"vue.vm"
))
else
if
(
template
.
contains
(
"index.vue.vm"
))
{
fileName
=
StringUtils
.
format
(
"{}/views/{}/{}/index.vue"
,
vuePath
,
moduleName
,
businessName
);
}
else
if
(
template
.
contains
(
"index-tree.vue.vm"
))
{
fileName
=
StringUtils
.
format
(
"{}/views/{}/{}/index.vue"
,
vuePath
,
moduleName
,
businessName
);
}
...
...
ruoyi/src/main/resources/application.yml
View file @
cb0a4b78
...
...
@@ -3,7 +3,7 @@ ruoyi:
# 名称
name
:
RuoYi
# 版本
version
:
2.
0
.0
version
:
2.
1
.0
# 版权年份
copyrightYear
:
2019
# 实例演示开关
...
...
ruoyi/src/main/resources/mybatis/monitor/SysLogininforMapper.xml
View file @
cb0a4b78
...
...
@@ -40,6 +40,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
and date_format(login_time,'%y%m%d')
<
= date_format(#{endTime},'%y%m%d')
</if>
</where>
order by info_id desc
</select>
<delete
id=
"deleteLogininforByIds"
parameterType=
"Long"
>
...
...
ruoyi/src/main/resources/mybatis/monitor/SysOperLogMapper.xml
View file @
cb0a4b78
...
...
@@ -25,7 +25,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<sql
id=
"selectOperLogVo"
>
select oper_id, title, business_type, method, request_method, operator_type, oper_name, dept_name, oper_url, oper_ip, oper_location, oper_param, json_result, status, error_msg, oper_time
from sys_oper_log
from sys_oper_log
order by oper_id desc
</sql>
<insert
id=
"insertOperlog"
parameterType=
"SysOperLog"
>
...
...
ruoyi/src/main/resources/vm/java/controller.java.vm
View file @
cb0a4b78
...
...
@@ -18,7 +18,10 @@ import ${packageName}.service.I${ClassName}Service;
import com.ruoyi.framework.web.controller.BaseController;
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.common.utils.poi.ExcelUtil;
#
if
($
table
.
crud
)
import com.ruoyi.framework.web.page.TableDataInfo;
#
elseif
($
table
.
tree
)
#
end
/**
*
${
functionName
}
Controller
...
...
@@ -38,12 +41,20 @@ public class ${ClassName}Controller extends BaseController
*/
@PreAuthorize("@ss.hasPermi('
${
permissionPrefix
}
:list')")
@GetMapping("/list")
#
if
($
table
.
crud
)
public TableDataInfo list(
${
ClassName
}
${
className
}
)
{
startPage();
List
<
${
ClassName
}
>
list =
${
className
}
Service.select
${
ClassName
}
List(
${
className
}
);
return getDataTable(list);
}
#
elseif
($
table
.
tree
)
public AjaxResult list(
${
ClassName
}
${
className
}
)
{
List
<
${
ClassName
}
>
list =
${
className
}
Service.select
${
ClassName
}
List(
${
className
}
);
return AjaxResult.success(list);
}
#
end
/**
* 导出
${
functionName
}
列表
...
...
ruoyi/src/main/resources/vm/java/domain.java.vm
View file @
cb0a4b78
...
...
@@ -3,7 +3,11 @@ package ${packageName}.domain;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.ruoyi.framework.aspectj.lang.annotation.Excel;
#
if
($
table
.
crud
)
import com.ruoyi.framework.web.domain.BaseEntity;
#
elseif
($
table
.
tree
)
import com.ruoyi.framework.web.domain.TreeEntity;
#
end
#
foreach
($
import
in
$
importList
)
import
${
import
}
;
#
end
...
...
@@ -14,7 +18,11 @@ import ${import};
* @author
${
author
}
* @date
${
datetime
}
*/
#
if
($
table
.
crud
)
#
set
($
Entity
=
"BaseEntity"
)
#
elseif
($
table
.
tree
)
#
set
($
Entity
=
"TreeEntity"
)
#
end
public class
${
ClassName
}
extends
${
Entity
}
{
private static final long serialVersionUID = 1L;
...
...
@@ -43,7 +51,7 @@ public class ${ClassName} extends ${Entity}
#
end
#
foreach
($
column
in
$
columns
)
#
if
(
!
$
table
.
isSuperColumn
($
column
.
javaField
))
#
if
($
column
.
javaField
>
2
&&
$
column
.
javaField
.
substring
(
1
,
2
).
matches
(
"[A-Z]"
))
#
if
($
column
.
javaField
.
length
()
>
2
&&
$
column
.
javaField
.
substring
(
1
,
2
).
matches
(
"[A-Z]"
))
#
set
($
AttrName
=
$
column
.
javaField
)
#
else
#
set
($
AttrName
=
$
column
.
javaField
.
substring
(
0
,
1
).
toUpperCase
()
+
${
column
.
javaField
.
substring
(
1
)})
...
...
@@ -64,7 +72,7 @@ public class ${ClassName} extends ${Entity}
public String toString()
{
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
#
foreach
($
column
in
$
columns
)
#
if
($
column
.
javaField
>
2
&&
$
column
.
javaField
.
substring
(
1
,
2
).
matches
(
"[A-Z]"
))
#
if
($
column
.
javaField
.
length
()
>
2
&&
$
column
.
javaField
.
substring
(
1
,
2
).
matches
(
"[A-Z]"
))
#
set
($
AttrName
=
$
column
.
javaField
)
#
else
#
set
($
AttrName
=
$
column
.
javaField
.
substring
(
0
,
1
).
toUpperCase
()
+
${
column
.
javaField
.
substring
(
1
)})
...
...
ruoyi/src/main/resources/vm/vue/index-tree.vue.vm
0 → 100644
View file @
cb0a4b78
<template>
<div
class=
"app-container"
>
<el-form
:model=
"queryParams"
ref=
"queryForm"
:inline=
"true"
label-width=
"68px"
>
#
foreach
($
column
in
$
columns
)
#
if
($
column
.
query
)
#
set
($
dictType
=
$
column
.
dictType
)
#
set
($
AttrName
=
$
column
.
javaField
.
substring
(
0
,
1
).
toUpperCase
()
+
${
column
.
javaField
.
substring
(
1
)})
#
set
($
parentheseIndex
=
$
column
.
columnComment
.
indexOf
(
"("
))
#
if
($
parentheseIndex
!=
-
1
)
#
set
($
comment
=
$
column
.
columnComment
.
substring
(
0
,
$
parentheseIndex
))
#
else
#
set
($
comment
=
$
column
.
columnComment
)
#
end
#
if
($
column
.
htmlType
==
"input"
)
<el-form-item
label=
"
${
comment
}
"
prop=
"
${
column
.
javaField
}
"
>
<el-input
v-model=
"queryParams.
${
column
.
javaField
}
"
placeholder=
"请输入
${
comment
}
"
clearable
size=
"small"
@
keyup.enter.native=
"handleQuery"
/>
</el-form-item>
#
elseif
(($
column
.
htmlType
==
"select"
||
$
column
.
htmlType
==
"radio"
)
&&
""
!=
$
dictType
)
<el-form-item
label=
"
${
comment
}
"
prop=
"
${
column
.
javaField
}
"
>
<el-select
v-model=
"queryParams.
${
column
.
javaField
}
"
placeholder=
"请选择
${
comment
}
"
clearable
size=
"small"
>
<el-option
v-for=
"dict in
${
column
.
javaField
}
Options"
:key=
"dict.dictValue"
:label=
"dict.dictLabel"
:value=
"dict.dictValue"
/>
</el-select>
</el-form-item>
#
elseif
(($
column
.
htmlType
==
"select"
||
$
column
.
htmlType
==
"radio"
)
&&
$
dictType
)
<el-form-item
label=
"
${
comment
}
"
prop=
"
${
column
.
javaField
}
"
>
<el-select
v-model=
"queryParams.
${
column
.
javaField
}
"
placeholder=
"请选择
${
comment
}
"
clearable
size=
"small"
>
<el-option
label=
"请选择字典生成"
value=
""
/>
</el-select>
</el-form-item>
#
elseif
($
column
.
htmlType
==
"datetime"
)
<el-form-item
label=
"
${
comment
}
"
prop=
"
${
column
.
javaField
}
"
>
<el-date-picker
clearable
size=
"small"
style=
"width: 200px"
v-model=
"queryParams.
${
column
.
javaField
}
"
type=
"date"
value-format=
"yyyy-MM-dd"
placeholder=
"选择
${
comment
}
"
>
</el-date-picker>
</el-form-item>
#
end
#
end
#
end
<el-form-item>
<el-button
class=
"filter-item"
type=
"primary"
icon=
"el-icon-search"
size=
"mini"
@
click=
"handleQuery"
>
搜索
</el-button>
<el-button
class=
"filter-item"
type=
"primary"
icon=
"el-icon-plus"
size=
"mini"
@
click=
"handleAdd"
v-hasPermi=
"['
${
moduleName
}
:
${
businessName
}
:add']"
>
新增
</el-button>
</el-form-item>
</el-form>
<el-table
v-loading=
"loading"
:data=
"
${
businessName
}
List"
row-key=
"
${
treeCode
}
"
default-expand-all
:tree-props=
"
{
children: 'children', hasChildren: 'hasChildren'}"
>
#
foreach
($
column
in
$
columns
)
#
set
($
javaField
=
$
column
.
javaField
)
#
set
($
parentheseIndex
=
$
column
.
columnComment
.
indexOf
(
"("
))
#
if
($
parentheseIndex
!=
-
1
)
#
set
($
comment
=
$
column
.
columnComment
.
substring
(
0
,
$
parentheseIndex
))
#
else
#
set
($
comment
=
$
column
.
columnComment
)
#
end
#
if
($
column
.
pk
)
#
elseif
($
column
.
list
&&
$
column
.
htmlType
==
"datetime"
)
<el-table-column
label=
"
${
comment
}
"
align=
"center"
prop=
"
${
javaField
}
"
width=
"180"
>
<template
slot-scope=
"scope"
>
<span>
{{
parseTime(scope.row.
${
javaField
}
) }}
</span>
</template>
</el-table-column>
#
elseif
($
column
.
list
&&
""
!=
$
column
.
dictType
)
<el-table-column
label=
"
${
comment
}
"
align=
"center"
prop=
"
${
javaField
}
"
:formatter=
"
${
javaField
}
Format"
/>
#
elseif
($
column
.
list
&&
""
!=
$
javaField
)
<el-table-column
label=
"
${
comment
}
"
align=
"center"
prop=
"
${
javaField
}
"
/>
#
end
#
end
<el-table-column
label=
"操作"
align=
"center"
class-name=
"small-padding fixed-width"
>
<template
slot-scope=
"scope"
>
<el-button
size=
"mini"
type=
"text"
icon=
"el-icon-edit"
@
click=
"handleUpdate(scope.row)"
v-hasPermi=
"['
${
moduleName
}
:
${
businessName
}
:edit']"
>
修改
</el-button>
<el-button
size=
"mini"
type=
"text"
icon=
"el-icon-delete"
@
click=
"handleDelete(scope.row)"
v-hasPermi=
"['
${
moduleName
}
:
${
businessName
}
:remove']"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 添加或修改
${
functionName
}
对话框 -->
<el-dialog
:title=
"title"
:visible.sync=
"open"
width=
"500px"
>
<el-form
ref=
"form"
:model=
"form"
:rules=
"rules"
label-width=
"80px"
>
#
foreach
($
column
in
$
columns
)
#
set
($
field
=
$
column
.
javaField
)
#
if
($
column
.
insert
&&
!
$
column
.
pk
)
#
if
(($
column
.
usableColumn
)
||
(
!
$
column
.
superColumn
))
#
set
($
parentheseIndex
=
$
column
.
columnComment
.
indexOf
(
"("
))
#
if
($
parentheseIndex
!=
-
1
)
#
set
($
comment
=
$
column
.
columnComment
.
substring
(
0
,
$
parentheseIndex
))
#
else
#
set
($
comment
=
$
column
.
columnComment
)
#
end
#
set
($
dictType
=
$
column
.
dictType
)
#
if
(
""
!=
$
treeParentCode
&&
$
column
.
javaField
==
$
treeParentCode
)
<el-form-item
label=
"
${
comment
}
"
prop=
"
${
treeParentCode
}
"
>
<treeselect
v-model=
"form.
${
treeParentCode
}
"
:options=
"
${
businessName
}
Options"
:normalizer=
"normalizer"
placeholder=
"请选择
${
comment
}
"
/>
</el-form-item>
#
elseif
($
column
.
htmlType
==
"input"
)
<el-form-item
label=
"
${
comment
}
"
prop=
"
${
field
}
"
>
<el-input
v-model=
"form.
${
field
}
"
placeholder=
"请输入
${
comment
}
"
/>
</el-form-item>
#
elseif
($
column
.
htmlType
==
"select"
&&
""
!=
$
dictType
)
<el-form-item
label=
"
${
comment
}
"
>
<el-select
v-model=
"form.
${
field
}
"
placeholder=
"请选择
${
comment
}
"
>
<el-option
v-for=
"dict in
${
field
}
Options"
:key=
"dict.dictValue"
:label=
"dict.dictLabel"
:value=
"dict.dictValue"
></el-option>
</el-select>
</el-form-item>
#
elseif
($
column
.
htmlType
==
"select"
&&
$
dictType
)
<el-form-item
label=
"
${
comment
}
"
>
<el-select
v-model=
"form.
${
field
}
"
placeholder=
"请选择
${
comment
}
"
>
<el-option
label=
"请选择字典生成"
value=
""
/>
</el-select>
</el-form-item>
#
elseif
($
column
.
htmlType
==
"radio"
&&
""
!=
$
dictType
)
<el-form-item
label=
"
${
comment
}
"
>
<el-radio-group
v-model=
"form.
${
field
}
"
>
<el-radio
v-for=
"dict in
${
field
}
Options"
:key=
"dict.dictValue"
:label=
"dict.dictValue"
>
{{
dict.dictLabel}}
</el-radio>
</el-radio-group>
</el-form-item>
#
elseif
($
column
.
htmlType
==
"radio"
&&
$
dictType
)
<el-form-item
label=
"
${
comment
}
"
>
<el-radio-group
v-model=
"form.
${
field
}
"
>
<el-radio
label=
"1"
>
请选择字典生成
</el-radio>
</el-radio-group>
</el-form-item>
#
elseif
($
column
.
htmlType
==
"datetime"
)
<el-form-item
label=
"
${
comment
}
"
prop=
"
${
field
}
"
>
<el-date-picker
clearable
size=
"small"
style=
"width: 200px"
v-model=
"form.
${
field
}
"
type=
"date"
value-format=
"yyyy-MM-dd"
placeholder=
"选择
${
comment
}
"
>
</el-date-picker>
</el-form-item>
#
elseif
($
column
.
htmlType
==
"textarea"
)
<el-form-item
label=
"
${
comment
}
"
prop=
"
${
field
}
"
>
<el-input
v-model=
"form.
${
field
}
"
type=
"textarea"
placeholder=
"请输入内容"
/>
</el-form-item>
#
end
#
end
#
end
#
end
</el-form>
<div
slot=
"footer"
class=
"dialog-footer"
>
<el-button
type=
"primary"
@
click=
"submitForm"
>
确 定
</el-button>
<el-button
@
click=
"cancel"
>
取 消
</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import
{
list
${
BusinessName
},
get
${
BusinessName
},
del
${
BusinessName
},
add
${
BusinessName
},
update
${
BusinessName
},
export
${
BusinessName
}
}
from
"
@/api/
${
moduleName
}
/
${
businessName
}
"
;
import
Treeselect
from
"
@riophae/vue-treeselect
"
;
import
"
@riophae/vue-treeselect/dist/vue-treeselect.css
"
;
export
default
{
name
:
"
${
BusinessName
}
"
,
components
:
{
Treeselect
},
data
()
{
return
{
// 遮罩层
loading
:
true
,
//
${
functionName
}
表格数据
${
businessName
}
List
:
[],
//
${
functionName
}
树选项
${
businessName
}
Options
:
[],
// 弹出层标题
title
:
""
,
// 是否显示弹出层
open
:
false
,
#
foreach
($
column
in
$
columns
)
#
set
($
parentheseIndex
=
$
column
.
columnComment
.
indexOf
(
"("
))
#
if
($
parentheseIndex
!=
-
1
)
#
set
($
comment
=
$
column
.
columnComment
.
substring
(
0
,
$
parentheseIndex
))
#
else
#
set
($
comment
=
$
column
.
columnComment
)
#
end
#
if
(${
column
.
dictType
}
!=
''
)
//
$
comment
字典
${
column
.
javaField
}
Options
:
[]#
if
($
velocityCount
!=
$
columns
.
size
()),#
end
#
end
#
end
// 查询参数
queryParams
:
{
#
foreach
($
column
in
$
columns
)
#
if
($
column
.
query
)
$
column
.
javaField
:
undefined
#
if
($
velocityCount
!=
$
columns
.
size
()),#
end
#
end
#
end
},
// 表单参数
form
:
{
},
// 表单校验
rules
:
{
#
foreach
($
column
in
$
columns
)
#
if
($
column
.
required
)
#
set
($
parentheseIndex
=
$
column
.
columnComment
.
indexOf
(
"("
))
#
if
($
parentheseIndex
!=
-
1
)
#
set
($
comment
=
$
column
.
columnComment
.
substring
(
0
,
$
parentheseIndex
))
#
else
#
set
($
comment
=
$
column
.
columnComment
)
#
end
#
set
($
comment
=
$
column
.
columnComment
)
$
column
.
javaField
:
[
{
required
:
true
,
message
:
"
$
comment
不能为空
"
,
trigger
:
"
blur
"
}
]#
if
($
velocityCount
!=
$
columns
.
size
()),#
end
#
end
#
end
}
};
},
created
()
{
this
.
getList
();
#
foreach
($
column
in
$
columns
)
#
if
(${
column
.
dictType
}
!=
''
)
this
.
getDicts
(
"
${
column
.
dictType
}
"
).
then
(
response
=>
{
this
.${
column
.
javaField
}
Options
=
response
.
data
;
});
#
end
#
end
},
methods
:
{
/** 查询
${
functionName
}
列表 */
getList
()
{
this
.
loading
=
true
;
list
${
BusinessName
}(
this
.
queryParams
).
then
(
response
=>
{
this
.${
businessName
}
List
=
this
.
handleTree
(
response
.
data
,
"
${
treeCode
}
"
,
"
${
treeParentCode
}
"
);
this
.
loading
=
false
;
});
},
/** 转换
${
functionName
}
数据结构 */
normalizer
(
node
)
{
if
(
node
.
children
&&
!
node
.
children
.
length
)
{
delete
node
.
children
;
}
return
{
id
:
node
.${
treeCode
},
label
:
node
.${
treeName
},
children
:
node
.
children
};
},
/** 查询部门下拉树结构 */
getTreeselect
()
{
list
${
BusinessName
}().
then
(
response
=>
{
this
.${
businessName
}
Options
=
[];
const
data
=
{
${
treeCode
}:
0
,
${
treeName
}:
'
顶级节点
'
,
children
:
[]
};
data
.
children
=
this
.
handleTree
(
response
.
data
,
"
${
treeCode
}
"
,
"
${
treeParentCode
}
"
);
this
.${
businessName
}
Options
.
push
(
data
);
});
},
#
foreach
($
column
in
$
columns
)
#
if
(${
column
.
dictType
}
!=
''
)
#
set
($
parentheseIndex
=
$
column
.
columnComment
.
indexOf
(
"("
))
#
if
($
parentheseIndex
!=
-
1
)
#
set
($
comment
=
$
column
.
columnComment
.
substring
(
0
,
$
parentheseIndex
))
#
else
#
set
($
comment
=
$
column
.
columnComment
)
#
end
//
$
comment
字典翻译
${
column
.
javaField
}
Format
(
row
,
column
)
{
return
this
.
selectDictLabel
(
this
.${
column
.
javaField
}
Options
,
row
.${
column
.
javaField
});
},
#
end
#
end
// 取消按钮
cancel
()
{
this
.
open
=
false
;
this
.
reset
();
},
// 表单重置
reset
()
{
this
.
form
=
{
#
foreach
($
column
in
$
columns
)
#
if
($
column
.
htmlType
==
"radio"
)
$
column
.
javaField
:
"
0
"
#
if
($
velocityCount
!=
$
columns
.
size
()),#
end
#
else
$
column
.
javaField
:
undefined
#
if
($
velocityCount
!=
$
columns
.
size
()),#
end
#
end
#
end
};
this
.
resetForm
(
"
form
"
);
},
/** 搜索按钮操作 */
handleQuery
()
{
this
.
getList
();
},
/** 重置按钮操作 */
resetQuery
()
{
this
.
resetForm
(
"
queryForm
"
);
this
.
handleQuery
();
},
/** 新增按钮操作 */
handleAdd
()
{
this
.
reset
();
this
.
getTreeselect
();
this
.
open
=
true
;
this
.
title
=
"
添加
${
functionName
}
"
;
},
/** 修改按钮操作 */
handleUpdate
(
row
)
{
this
.
reset
();
this
.
getTreeselect
();
if
(
row
!=
undefined
)
{
this
.
form
.${
treeParentCode
}
=
row
.${
treeCode
};
}
get
${
BusinessName
}(
row
.${
pkColumn
.
javaField
}).
then
(
response
=>
{
this
.
form
=
response
.
data
;
this
.
open
=
true
;
this
.
title
=
"
修改
${
functionName
}
"
;
});
},
/** 提交按钮 */
submitForm
:
function
()
{
this
.
#
[[$]]#
refs
[
"
form
"
].
validate
(
valid
=>
{
if
(
valid
)
{
if
(
this
.
form
.${
pkColumn
.
javaField
}
!=
undefined
)
{
update
${
BusinessName
}(
this
.
form
).
then
(
response
=>
{
if
(
response
.
code
===
200
)
{
this
.
msgSuccess
(
"
修改成功
"
);
this
.
open
=
false
;
this
.
getList
();
}
else
{
this
.
msgError
(
response
.
msg
);
}
});
}
else
{
add
${
BusinessName
}(
this
.
form
).
then
(
response
=>
{
if
(
response
.
code
===
200
)
{
this
.
msgSuccess
(
"
新增成功
"
);
this
.
open
=
false
;
this
.
getList
();
}
else
{
this
.
msgError
(
response
.
msg
);
}
});
}
}
});
},
/** 删除按钮操作 */
handleDelete
(
row
)
{
this
.$
confirm
(
'是否确认删除${functionName}编号为"'
+
row.
${
pkColumn
.
javaField
}
+
'"的数据项?'
,
"警告"
,
{
confirmButtonText:
"确定"
,
cancelButtonText:
"取消"
,
type:
"warning"
}).
then
(
function
()
{
return
del
${
BusinessName
}(
row
.${
pkColumn
.
javaField
});
}).
then
(()
=>
{
this
.
getList
();
this
.
msgSuccess
(
"
删除成功
"
);
}).
catch
(
function
()
{
});
}
}
};
</script>
\ No newline at end of file
Prev
1
2
3
4
Next
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment