Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
F
finance-manage
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
finance-oa
finance-manage
Commits
a29201a2
Commit
a29201a2
authored
Feb 09, 2022
by
稚屿
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
修正单词拼写错误
parent
612c4293
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
1662 additions
and
1662 deletions
+1662
-1662
ruoyi-ui/src/utils/generator/drawingDefault.js
ruoyi-ui/src/utils/generator/drawingDefault.js
+29
-29
ruoyi-ui/src/utils/generator/html.js
ruoyi-ui/src/utils/generator/html.js
+359
-359
ruoyi-ui/src/utils/generator/js.js
ruoyi-ui/src/utils/generator/js.js
+236
-236
ruoyi-ui/src/views/tool/build/CodeTypeDialog.vue
ruoyi-ui/src/views/tool/build/CodeTypeDialog.vue
+106
-106
ruoyi-ui/src/views/tool/build/TreeNodeDialog.vue
ruoyi-ui/src/views/tool/build/TreeNodeDialog.vue
+149
-149
ruoyi-ui/src/views/tool/build/index.vue
ruoyi-ui/src/views/tool/build/index.vue
+783
-783
No files found.
ruoyi-ui/src/utils/generator/drawingDefa
lu
t.js
→
ruoyi-ui/src/utils/generator/drawingDefa
ul
t.js
View file @
a29201a2
export
default
[
{
layout
:
'
colFormItem
'
,
tagIcon
:
'
input
'
,
label
:
'
手机号
'
,
vModel
:
'
mobile
'
,
formId
:
6
,
tag
:
'
el-input
'
,
placeholder
:
'
请输入手机号
'
,
defaultValue
:
''
,
span
:
24
,
style
:
{
width
:
'
100%
'
},
clearable
:
true
,
prepend
:
''
,
append
:
''
,
'
prefix-icon
'
:
'
el-icon-mobile
'
,
'
suffix-icon
'
:
''
,
maxlength
:
11
,
'
show-word-limit
'
:
true
,
readonly
:
false
,
disabled
:
false
,
required
:
true
,
changeTag
:
true
,
regList
:
[{
pattern
:
'
/^1(3|4|5|7|8|9)
\\
d{9}$/
'
,
message
:
'
手机号格式错误
'
}]
}
]
export
default
[
{
layout
:
'
colFormItem
'
,
tagIcon
:
'
input
'
,
label
:
'
手机号
'
,
vModel
:
'
mobile
'
,
formId
:
6
,
tag
:
'
el-input
'
,
placeholder
:
'
请输入手机号
'
,
defaultValue
:
''
,
span
:
24
,
style
:
{
width
:
'
100%
'
},
clearable
:
true
,
prepend
:
''
,
append
:
''
,
'
prefix-icon
'
:
'
el-icon-mobile
'
,
'
suffix-icon
'
:
''
,
maxlength
:
11
,
'
show-word-limit
'
:
true
,
readonly
:
false
,
disabled
:
false
,
required
:
true
,
changeTag
:
true
,
regList
:
[{
pattern
:
'
/^1(3|4|5|7|8|9)
\\
d{9}$/
'
,
message
:
'
手机号格式错误
'
}]
}
]
ruoyi-ui/src/utils/generator/html.js
View file @
a29201a2
/* eslint-disable max-len */
import
{
trigger
}
from
'
./config
'
let
confGlobal
let
someSpanIsNot24
export
function
dialogWrapper
(
str
)
{
return
`<el-dialog v-bind="$attrs" v-on="$listeners" @open="onOpen" @close="onClose" title="Dialog Tit
ile">
${
str
}
<div slot="footer">
<el-button @click="close">取消</el-button>
<el-button type="primary" @click="hand
elConfirm">确定</el-button>
</div>
</el-dialog>`
}
export
function
vueTemplate
(
str
)
{
return
`<template>
<div>
${
str
}
</div>
</template>`
}
export
function
vueScript
(
str
)
{
return
`<script>
${
str
}
</script>`
}
export
function
cssStyle
(
cssStr
)
{
return
`<style>
${
cssStr
}
</style>`
}
function
buildFormTemplate
(
conf
,
child
,
type
)
{
let
labelPosition
=
''
if
(
conf
.
labelPosition
!==
'
right
'
)
{
labelPosition
=
`label-position="
${
conf
.
labelPosition
}
"`
}
const
disabled
=
conf
.
disabled
?
`:disabled="
${
conf
.
disabled
}
"`
:
''
let
str
=
`<el-form ref="
${
conf
.
formRef
}
" :model="
${
conf
.
formModel
}
" :rules="
${
conf
.
formRules
}
" size="
${
conf
.
size
}
"
${
disabled
}
label-width="
${
conf
.
labelWidth
}
px"
${
labelPosition
}
>
${
child
}
${
buildFromBtns
(
conf
,
type
)}
</el-form>`
if
(
someSpanIsNot24
)
{
str
=
`<el-row :gutter="
${
conf
.
gutter
}
">
${
str
}
</el-row>`
}
return
str
}
function
buildFromBtns
(
conf
,
type
)
{
let
str
=
''
if
(
conf
.
formBtns
&&
type
===
'
file
'
)
{
str
=
`<el-form-item size="large">
<el-button type="primary" @click="submitForm">提交</el-button>
<el-button @click="resetForm">重置</el-button>
</el-form-item>`
if
(
someSpanIsNot24
)
{
str
=
`<el-col :span="24">
${
str
}
</el-col>`
}
}
return
str
}
// span不为24的用el-col包裹
function
colWrapper
(
element
,
str
)
{
if
(
someSpanIsNot24
||
element
.
span
!==
24
)
{
return
`<el-col :span="
${
element
.
span
}
">
${
str
}
</el-col>`
}
return
str
}
const
layouts
=
{
colFormItem
(
element
)
{
let
labelWidth
=
''
if
(
element
.
labelWidth
&&
element
.
labelWidth
!==
confGlobal
.
labelWidth
)
{
labelWidth
=
`label-width="
${
element
.
labelWidth
}
px"`
}
const
required
=
!
trigger
[
element
.
tag
]
&&
element
.
required
?
'
required
'
:
''
const
tagDom
=
tags
[
element
.
tag
]
?
tags
[
element
.
tag
](
element
)
:
null
let
str
=
`<el-form-item
${
labelWidth
}
label="
${
element
.
label
}
" prop="
${
element
.
vModel
}
"
${
required
}
>
${
tagDom
}
</el-form-item>`
str
=
colWrapper
(
element
,
str
)
return
str
},
rowFormItem
(
element
)
{
const
type
=
element
.
type
===
'
default
'
?
''
:
`type="
${
element
.
type
}
"`
const
justify
=
element
.
type
===
'
default
'
?
''
:
`justify="
${
element
.
justify
}
"`
const
align
=
element
.
type
===
'
default
'
?
''
:
`align="
${
element
.
align
}
"`
const
gutter
=
element
.
gutter
?
`gutter="
${
element
.
gutter
}
"`
:
''
const
children
=
element
.
children
.
map
(
el
=>
layouts
[
el
.
layout
](
el
))
let
str
=
`<el-row
${
type
}
${
justify
}
${
align
}
${
gutter
}
>
${
children
.
join
(
'
\n
'
)}
</el-row>`
str
=
colWrapper
(
element
,
str
)
return
str
}
}
const
tags
=
{
'
el-button
'
:
el
=>
{
const
{
tag
,
disabled
}
=
attrBuilder
(
el
)
const
type
=
el
.
type
?
`type="
${
el
.
type
}
"`
:
''
const
icon
=
el
.
icon
?
`icon="
${
el
.
icon
}
"`
:
''
const
size
=
el
.
size
?
`size="
${
el
.
size
}
"`
:
''
let
child
=
buildElButtonChild
(
el
)
if
(
child
)
child
=
`\n
${
child
}
\n`
// 换行
return
`<
${
el
.
tag
}
${
type
}
${
icon
}
${
size
}
${
disabled
}
>
${
child
}
</
${
el
.
tag
}
>`
},
'
el-input
'
:
el
=>
{
const
{
disabled
,
vModel
,
clearable
,
placeholder
,
width
}
=
attrBuilder
(
el
)
const
maxlength
=
el
.
maxlength
?
`:maxlength="
${
el
.
maxlength
}
"`
:
''
const
showWordLimit
=
el
[
'
show-word-limit
'
]
?
'
show-word-limit
'
:
''
const
readonly
=
el
.
readonly
?
'
readonly
'
:
''
const
prefixIcon
=
el
[
'
prefix-icon
'
]
?
`prefix-icon='
${
el
[
'
prefix-icon
'
]}
'`
:
''
const
suffixIcon
=
el
[
'
suffix-icon
'
]
?
`suffix-icon='
${
el
[
'
suffix-icon
'
]}
'`
:
''
const
showPassword
=
el
[
'
show-password
'
]
?
'
show-password
'
:
''
const
type
=
el
.
type
?
`type="
${
el
.
type
}
"`
:
''
const
autosize
=
el
.
autosize
&&
el
.
autosize
.
minRows
?
`:autosize="{minRows:
${
el
.
autosize
.
minRows
}
, maxRows:
${
el
.
autosize
.
maxRows
}
}"`
:
''
let
child
=
buildElInputChild
(
el
)
if
(
child
)
child
=
`\n
${
child
}
\n`
// 换行
return
`<
${
el
.
tag
}
${
vModel
}
${
type
}
${
placeholder
}
${
maxlength
}
${
showWordLimit
}
${
readonly
}
${
disabled
}
${
clearable
}
${
prefixIcon
}
${
suffixIcon
}
${
showPassword
}
${
autosize
}
${
width
}
>
${
child
}
</
${
el
.
tag
}
>`
},
'
el-input-number
'
:
el
=>
{
const
{
disabled
,
vModel
,
placeholder
}
=
attrBuilder
(
el
)
const
controlsPosition
=
el
[
'
controls-position
'
]
?
`controls-position=
${
el
[
'
controls-position
'
]}
`
:
''
const
min
=
el
.
min
?
`:min='
${
el
.
min
}
'`
:
''
const
max
=
el
.
max
?
`:max='
${
el
.
max
}
'`
:
''
const
step
=
el
.
step
?
`:step='
${
el
.
step
}
'`
:
''
const
stepStrictly
=
el
[
'
step-strictly
'
]
?
'
step-strictly
'
:
''
const
precision
=
el
.
precision
?
`:precision='
${
el
.
precision
}
'`
:
''
return
`<
${
el
.
tag
}
${
vModel
}
${
placeholder
}
${
step
}
${
stepStrictly
}
${
precision
}
${
controlsPosition
}
${
min
}
${
max
}
${
disabled
}
></
${
el
.
tag
}
>`
},
'
el-select
'
:
el
=>
{
const
{
disabled
,
vModel
,
clearable
,
placeholder
,
width
}
=
attrBuilder
(
el
)
const
filterable
=
el
.
filterable
?
'
filterable
'
:
''
const
multiple
=
el
.
multiple
?
'
multiple
'
:
''
let
child
=
buildElSelectChild
(
el
)
if
(
child
)
child
=
`\n
${
child
}
\n`
// 换行
return
`<
${
el
.
tag
}
${
vModel
}
${
placeholder
}
${
disabled
}
${
multiple
}
${
filterable
}
${
clearable
}
${
width
}
>
${
child
}
</
${
el
.
tag
}
>`
},
'
el-radio-group
'
:
el
=>
{
const
{
disabled
,
vModel
}
=
attrBuilder
(
el
)
const
size
=
`size="
${
el
.
size
}
"`
let
child
=
buildElRadioGroupChild
(
el
)
if
(
child
)
child
=
`\n
${
child
}
\n`
// 换行
return
`<
${
el
.
tag
}
${
vModel
}
${
size
}
${
disabled
}
>
${
child
}
</
${
el
.
tag
}
>`
},
'
el-checkbox-group
'
:
el
=>
{
const
{
disabled
,
vModel
}
=
attrBuilder
(
el
)
const
size
=
`size="
${
el
.
size
}
"`
const
min
=
el
.
min
?
`:min="
${
el
.
min
}
"`
:
''
const
max
=
el
.
max
?
`:max="
${
el
.
max
}
"`
:
''
let
child
=
buildElCheckboxGroupChild
(
el
)
if
(
child
)
child
=
`\n
${
child
}
\n`
// 换行
return
`<
${
el
.
tag
}
${
vModel
}
${
min
}
${
max
}
${
size
}
${
disabled
}
>
${
child
}
</
${
el
.
tag
}
>`
},
'
el-switch
'
:
el
=>
{
const
{
disabled
,
vModel
}
=
attrBuilder
(
el
)
const
activeText
=
el
[
'
active-text
'
]
?
`active-text="
${
el
[
'
active-text
'
]}
"`
:
''
const
inactiveText
=
el
[
'
inactive-text
'
]
?
`inactive-text="
${
el
[
'
inactive-text
'
]}
"`
:
''
const
activeColor
=
el
[
'
active-color
'
]
?
`active-color="
${
el
[
'
active-color
'
]}
"`
:
''
const
inactiveColor
=
el
[
'
inactive-color
'
]
?
`inactive-color="
${
el
[
'
inactive-color
'
]}
"`
:
''
const
activeValue
=
el
[
'
active-value
'
]
!==
true
?
`:active-value='
${
JSON
.
stringify
(
el
[
'
active-value
'
])}
'`
:
''
const
inactiveValue
=
el
[
'
inactive-value
'
]
!==
false
?
`:inactive-value='
${
JSON
.
stringify
(
el
[
'
inactive-value
'
])}
'`
:
''
return
`<
${
el
.
tag
}
${
vModel
}
${
activeText
}
${
inactiveText
}
${
activeColor
}
${
inactiveColor
}
${
activeValue
}
${
inactiveValue
}
${
disabled
}
></
${
el
.
tag
}
>`
},
'
el-cascader
'
:
el
=>
{
const
{
disabled
,
vModel
,
clearable
,
placeholder
,
width
}
=
attrBuilder
(
el
)
const
options
=
el
.
options
?
`:options="
${
el
.
vModel
}
Options"`
:
''
const
props
=
el
.
props
?
`:props="
${
el
.
vModel
}
Props"`
:
''
const
showAllLevels
=
el
[
'
show-all-levels
'
]
?
''
:
'
:show-all-levels="false"
'
const
filterable
=
el
.
filterable
?
'
filterable
'
:
''
const
separator
=
el
.
separator
===
'
/
'
?
''
:
`separator="
${
el
.
separator
}
"`
return
`<
${
el
.
tag
}
${
vModel
}
${
options
}
${
props
}
${
width
}
${
showAllLevels
}
${
placeholder
}
${
separator
}
${
filterable
}
${
clearable
}
${
disabled
}
></
${
el
.
tag
}
>`
},
'
el-slider
'
:
el
=>
{
const
{
disabled
,
vModel
}
=
attrBuilder
(
el
)
const
min
=
el
.
min
?
`:min='
${
el
.
min
}
'`
:
''
const
max
=
el
.
max
?
`:max='
${
el
.
max
}
'`
:
''
const
step
=
el
.
step
?
`:step='
${
el
.
step
}
'`
:
''
const
range
=
el
.
range
?
'
range
'
:
''
const
showStops
=
el
[
'
show-stops
'
]
?
`:show-stops="
${
el
[
'
show-stops
'
]}
"`
:
''
return
`<
${
el
.
tag
}
${
min
}
${
max
}
${
step
}
${
vModel
}
${
range
}
${
showStops
}
${
disabled
}
></
${
el
.
tag
}
>`
},
'
el-time-picker
'
:
el
=>
{
const
{
disabled
,
vModel
,
clearable
,
placeholder
,
width
}
=
attrBuilder
(
el
)
const
startPlaceholder
=
el
[
'
start-placeholder
'
]
?
`start-placeholder="
${
el
[
'
start-placeholder
'
]}
"`
:
''
const
endPlaceholder
=
el
[
'
end-placeholder
'
]
?
`end-placeholder="
${
el
[
'
end-placeholder
'
]}
"`
:
''
const
rangeSeparator
=
el
[
'
range-separator
'
]
?
`range-separator="
${
el
[
'
range-separator
'
]}
"`
:
''
const
isRange
=
el
[
'
is-range
'
]
?
'
is-range
'
:
''
const
format
=
el
.
format
?
`format="
${
el
.
format
}
"`
:
''
const
valueFormat
=
el
[
'
value-format
'
]
?
`value-format="
${
el
[
'
value-format
'
]}
"`
:
''
const
pickerOptions
=
el
[
'
picker-options
'
]
?
`:picker-options='
${
JSON
.
stringify
(
el
[
'
picker-options
'
])}
'`
:
''
return
`<
${
el
.
tag
}
${
vModel
}
${
isRange
}
${
format
}
${
valueFormat
}
${
pickerOptions
}
${
width
}
${
placeholder
}
${
startPlaceholder
}
${
endPlaceholder
}
${
rangeSeparator
}
${
clearable
}
${
disabled
}
></
${
el
.
tag
}
>`
},
'
el-date-picker
'
:
el
=>
{
const
{
disabled
,
vModel
,
clearable
,
placeholder
,
width
}
=
attrBuilder
(
el
)
const
startPlaceholder
=
el
[
'
start-placeholder
'
]
?
`start-placeholder="
${
el
[
'
start-placeholder
'
]}
"`
:
''
const
endPlaceholder
=
el
[
'
end-placeholder
'
]
?
`end-placeholder="
${
el
[
'
end-placeholder
'
]}
"`
:
''
const
rangeSeparator
=
el
[
'
range-separator
'
]
?
`range-separator="
${
el
[
'
range-separator
'
]}
"`
:
''
const
format
=
el
.
format
?
`format="
${
el
.
format
}
"`
:
''
const
valueFormat
=
el
[
'
value-format
'
]
?
`value-format="
${
el
[
'
value-format
'
]}
"`
:
''
const
type
=
el
.
type
===
'
date
'
?
''
:
`type="
${
el
.
type
}
"`
const
readonly
=
el
.
readonly
?
'
readonly
'
:
''
return
`<
${
el
.
tag
}
${
type
}
${
vModel
}
${
format
}
${
valueFormat
}
${
width
}
${
placeholder
}
${
startPlaceholder
}
${
endPlaceholder
}
${
rangeSeparator
}
${
clearable
}
${
readonly
}
${
disabled
}
></
${
el
.
tag
}
>`
},
'
el-rate
'
:
el
=>
{
const
{
disabled
,
vModel
}
=
attrBuilder
(
el
)
const
max
=
el
.
max
?
`:max='
${
el
.
max
}
'`
:
''
const
allowHalf
=
el
[
'
allow-half
'
]
?
'
allow-half
'
:
''
const
showText
=
el
[
'
show-text
'
]
?
'
show-text
'
:
''
const
showScore
=
el
[
'
show-score
'
]
?
'
show-score
'
:
''
return
`<
${
el
.
tag
}
${
vModel
}
${
allowHalf
}
${
showText
}
${
showScore
}
${
disabled
}
></
${
el
.
tag
}
>`
},
'
el-color-picker
'
:
el
=>
{
const
{
disabled
,
vModel
}
=
attrBuilder
(
el
)
const
size
=
`size="
${
el
.
size
}
"`
const
showAlpha
=
el
[
'
show-alpha
'
]
?
'
show-alpha
'
:
''
const
colorFormat
=
el
[
'
color-format
'
]
?
`color-format="
${
el
[
'
color-format
'
]}
"`
:
''
return
`<
${
el
.
tag
}
${
vModel
}
${
size
}
${
showAlpha
}
${
colorFormat
}
${
disabled
}
></
${
el
.
tag
}
>`
},
'
el-upload
'
:
el
=>
{
const
disabled
=
el
.
disabled
?
'
:disabled=
\'
true
\'
'
:
''
const
action
=
el
.
action
?
`:action="
${
el
.
vModel
}
Action"`
:
''
const
multiple
=
el
.
multiple
?
'
multiple
'
:
''
const
listType
=
el
[
'
list-type
'
]
!==
'
text
'
?
`list-type="
${
el
[
'
list-type
'
]}
"`
:
''
const
accept
=
el
.
accept
?
`accept="
${
el
.
accept
}
"`
:
''
const
name
=
el
.
name
!==
'
file
'
?
`name="
${
el
.
name
}
"`
:
''
const
autoUpload
=
el
[
'
auto-upload
'
]
===
false
?
'
:auto-upload="false"
'
:
''
const
beforeUpload
=
`:before-upload="
${
el
.
vModel
}
BeforeUpload"`
const
fileList
=
`:file-list="
${
el
.
vModel
}
fileList"`
const
ref
=
`ref="
${
el
.
vModel
}
"`
let
child
=
buildElUploadChild
(
el
)
if
(
child
)
child
=
`\n
${
child
}
\n`
// 换行
return
`<
${
el
.
tag
}
${
ref
}
${
fileList
}
${
action
}
${
autoUpload
}
${
multiple
}
${
beforeUpload
}
${
listType
}
${
accept
}
${
name
}
${
disabled
}
>
${
child
}
</
${
el
.
tag
}
>`
}
}
function
attrBuilder
(
el
)
{
return
{
vModel
:
`v-model="
${
confGlobal
.
formModel
}
.
${
el
.
vModel
}
"`
,
clearable
:
el
.
clearable
?
'
clearable
'
:
''
,
placeholder
:
el
.
placeholder
?
`placeholder="
${
el
.
placeholder
}
"`
:
''
,
width
:
el
.
style
&&
el
.
style
.
width
?
'
:style="{width:
\'
100%
\'
}"
'
:
''
,
disabled
:
el
.
disabled
?
'
:disabled=
\'
true
\'
'
:
''
}
}
// el-buttin 子级
function
buildElButtonChild
(
conf
)
{
const
children
=
[]
if
(
conf
.
default
)
{
children
.
push
(
conf
.
default
)
}
return
children
.
join
(
'
\n
'
)
}
// el-input innerHTML
function
buildElInputChild
(
conf
)
{
const
children
=
[]
if
(
conf
.
prepend
)
{
children
.
push
(
`<template slot="prepend">
${
conf
.
prepend
}
</template>`
)
}
if
(
conf
.
append
)
{
children
.
push
(
`<template slot="append">
${
conf
.
append
}
</template>`
)
}
return
children
.
join
(
'
\n
'
)
}
function
buildElSelectChild
(
conf
)
{
const
children
=
[]
if
(
conf
.
options
&&
conf
.
options
.
length
)
{
children
.
push
(
`<el-option v-for="(item, index) in
${
conf
.
vModel
}
Options" :key="index" :label="item.label" :value="item.value" :disabled="item.disabled"></el-option>`
)
}
return
children
.
join
(
'
\n
'
)
}
function
buildElRadioGroupChild
(
conf
)
{
const
children
=
[]
if
(
conf
.
options
&&
conf
.
options
.
length
)
{
const
tag
=
conf
.
optionType
===
'
button
'
?
'
el-radio-button
'
:
'
el-radio
'
const
border
=
conf
.
border
?
'
border
'
:
''
children
.
push
(
`<
${
tag
}
v-for="(item, index) in
${
conf
.
vModel
}
Options" :key="index" :label="item.value" :disabled="item.disabled"
${
border
}
>{{item.label}}</
${
tag
}
>`
)
}
return
children
.
join
(
'
\n
'
)
}
function
buildElCheckboxGroupChild
(
conf
)
{
const
children
=
[]
if
(
conf
.
options
&&
conf
.
options
.
length
)
{
const
tag
=
conf
.
optionType
===
'
button
'
?
'
el-checkbox-button
'
:
'
el-checkbox
'
const
border
=
conf
.
border
?
'
border
'
:
''
children
.
push
(
`<
${
tag
}
v-for="(item, index) in
${
conf
.
vModel
}
Options" :key="index" :label="item.value" :disabled="item.disabled"
${
border
}
>{{item.label}}</
${
tag
}
>`
)
}
return
children
.
join
(
'
\n
'
)
}
function
buildElUploadChild
(
conf
)
{
const
list
=
[]
if
(
conf
[
'
list-type
'
]
===
'
picture-card
'
)
list
.
push
(
'
<i class="el-icon-plus"></i>
'
)
else
list
.
push
(
`<el-button size="small" type="primary" icon="el-icon-upload">
${
conf
.
buttonText
}
</el-button>`
)
if
(
conf
.
showTip
)
list
.
push
(
`<div slot="tip" class="el-upload__tip">只能上传不超过
${
conf
.
fileSize
}${
conf
.
sizeUnit
}
的
${
conf
.
accept
}
文件</div>`
)
return
list
.
join
(
'
\n
'
)
}
export
function
makeUpHtml
(
conf
,
type
)
{
const
htmlList
=
[]
confGlobal
=
conf
someSpanIsNot24
=
conf
.
fields
.
some
(
item
=>
item
.
span
!==
24
)
conf
.
fields
.
forEach
(
el
=>
{
htmlList
.
push
(
layouts
[
el
.
layout
](
el
))
})
const
htmlStr
=
htmlList
.
join
(
'
\n
'
)
let
temp
=
buildFormTemplate
(
conf
,
htmlStr
,
type
)
if
(
type
===
'
dialog
'
)
{
temp
=
dialogWrapper
(
temp
)
}
confGlobal
=
null
return
temp
}
/* eslint-disable max-len */
import
{
trigger
}
from
'
./config
'
let
confGlobal
let
someSpanIsNot24
export
function
dialogWrapper
(
str
)
{
return
`<el-dialog v-bind="$attrs" v-on="$listeners" @open="onOpen" @close="onClose" title="Dialog Tit
le">
${
str
}
<div slot="footer">
<el-button @click="close">取消</el-button>
<el-button type="primary" @click="hand
leConfirm">确定</el-button>
</div>
</el-dialog>`
}
export
function
vueTemplate
(
str
)
{
return
`<template>
<div>
${
str
}
</div>
</template>`
}
export
function
vueScript
(
str
)
{
return
`<script>
${
str
}
</script>`
}
export
function
cssStyle
(
cssStr
)
{
return
`<style>
${
cssStr
}
</style>`
}
function
buildFormTemplate
(
conf
,
child
,
type
)
{
let
labelPosition
=
''
if
(
conf
.
labelPosition
!==
'
right
'
)
{
labelPosition
=
`label-position="
${
conf
.
labelPosition
}
"`
}
const
disabled
=
conf
.
disabled
?
`:disabled="
${
conf
.
disabled
}
"`
:
''
let
str
=
`<el-form ref="
${
conf
.
formRef
}
" :model="
${
conf
.
formModel
}
" :rules="
${
conf
.
formRules
}
" size="
${
conf
.
size
}
"
${
disabled
}
label-width="
${
conf
.
labelWidth
}
px"
${
labelPosition
}
>
${
child
}
${
buildFromBtns
(
conf
,
type
)}
</el-form>`
if
(
someSpanIsNot24
)
{
str
=
`<el-row :gutter="
${
conf
.
gutter
}
">
${
str
}
</el-row>`
}
return
str
}
function
buildFromBtns
(
conf
,
type
)
{
let
str
=
''
if
(
conf
.
formBtns
&&
type
===
'
file
'
)
{
str
=
`<el-form-item size="large">
<el-button type="primary" @click="submitForm">提交</el-button>
<el-button @click="resetForm">重置</el-button>
</el-form-item>`
if
(
someSpanIsNot24
)
{
str
=
`<el-col :span="24">
${
str
}
</el-col>`
}
}
return
str
}
// span不为24的用el-col包裹
function
colWrapper
(
element
,
str
)
{
if
(
someSpanIsNot24
||
element
.
span
!==
24
)
{
return
`<el-col :span="
${
element
.
span
}
">
${
str
}
</el-col>`
}
return
str
}
const
layouts
=
{
colFormItem
(
element
)
{
let
labelWidth
=
''
if
(
element
.
labelWidth
&&
element
.
labelWidth
!==
confGlobal
.
labelWidth
)
{
labelWidth
=
`label-width="
${
element
.
labelWidth
}
px"`
}
const
required
=
!
trigger
[
element
.
tag
]
&&
element
.
required
?
'
required
'
:
''
const
tagDom
=
tags
[
element
.
tag
]
?
tags
[
element
.
tag
](
element
)
:
null
let
str
=
`<el-form-item
${
labelWidth
}
label="
${
element
.
label
}
" prop="
${
element
.
vModel
}
"
${
required
}
>
${
tagDom
}
</el-form-item>`
str
=
colWrapper
(
element
,
str
)
return
str
},
rowFormItem
(
element
)
{
const
type
=
element
.
type
===
'
default
'
?
''
:
`type="
${
element
.
type
}
"`
const
justify
=
element
.
type
===
'
default
'
?
''
:
`justify="
${
element
.
justify
}
"`
const
align
=
element
.
type
===
'
default
'
?
''
:
`align="
${
element
.
align
}
"`
const
gutter
=
element
.
gutter
?
`gutter="
${
element
.
gutter
}
"`
:
''
const
children
=
element
.
children
.
map
(
el
=>
layouts
[
el
.
layout
](
el
))
let
str
=
`<el-row
${
type
}
${
justify
}
${
align
}
${
gutter
}
>
${
children
.
join
(
'
\n
'
)}
</el-row>`
str
=
colWrapper
(
element
,
str
)
return
str
}
}
const
tags
=
{
'
el-button
'
:
el
=>
{
const
{
tag
,
disabled
}
=
attrBuilder
(
el
)
const
type
=
el
.
type
?
`type="
${
el
.
type
}
"`
:
''
const
icon
=
el
.
icon
?
`icon="
${
el
.
icon
}
"`
:
''
const
size
=
el
.
size
?
`size="
${
el
.
size
}
"`
:
''
let
child
=
buildElButtonChild
(
el
)
if
(
child
)
child
=
`\n
${
child
}
\n`
// 换行
return
`<
${
el
.
tag
}
${
type
}
${
icon
}
${
size
}
${
disabled
}
>
${
child
}
</
${
el
.
tag
}
>`
},
'
el-input
'
:
el
=>
{
const
{
disabled
,
vModel
,
clearable
,
placeholder
,
width
}
=
attrBuilder
(
el
)
const
maxlength
=
el
.
maxlength
?
`:maxlength="
${
el
.
maxlength
}
"`
:
''
const
showWordLimit
=
el
[
'
show-word-limit
'
]
?
'
show-word-limit
'
:
''
const
readonly
=
el
.
readonly
?
'
readonly
'
:
''
const
prefixIcon
=
el
[
'
prefix-icon
'
]
?
`prefix-icon='
${
el
[
'
prefix-icon
'
]}
'`
:
''
const
suffixIcon
=
el
[
'
suffix-icon
'
]
?
`suffix-icon='
${
el
[
'
suffix-icon
'
]}
'`
:
''
const
showPassword
=
el
[
'
show-password
'
]
?
'
show-password
'
:
''
const
type
=
el
.
type
?
`type="
${
el
.
type
}
"`
:
''
const
autosize
=
el
.
autosize
&&
el
.
autosize
.
minRows
?
`:autosize="{minRows:
${
el
.
autosize
.
minRows
}
, maxRows:
${
el
.
autosize
.
maxRows
}
}"`
:
''
let
child
=
buildElInputChild
(
el
)
if
(
child
)
child
=
`\n
${
child
}
\n`
// 换行
return
`<
${
el
.
tag
}
${
vModel
}
${
type
}
${
placeholder
}
${
maxlength
}
${
showWordLimit
}
${
readonly
}
${
disabled
}
${
clearable
}
${
prefixIcon
}
${
suffixIcon
}
${
showPassword
}
${
autosize
}
${
width
}
>
${
child
}
</
${
el
.
tag
}
>`
},
'
el-input-number
'
:
el
=>
{
const
{
disabled
,
vModel
,
placeholder
}
=
attrBuilder
(
el
)
const
controlsPosition
=
el
[
'
controls-position
'
]
?
`controls-position=
${
el
[
'
controls-position
'
]}
`
:
''
const
min
=
el
.
min
?
`:min='
${
el
.
min
}
'`
:
''
const
max
=
el
.
max
?
`:max='
${
el
.
max
}
'`
:
''
const
step
=
el
.
step
?
`:step='
${
el
.
step
}
'`
:
''
const
stepStrictly
=
el
[
'
step-strictly
'
]
?
'
step-strictly
'
:
''
const
precision
=
el
.
precision
?
`:precision='
${
el
.
precision
}
'`
:
''
return
`<
${
el
.
tag
}
${
vModel
}
${
placeholder
}
${
step
}
${
stepStrictly
}
${
precision
}
${
controlsPosition
}
${
min
}
${
max
}
${
disabled
}
></
${
el
.
tag
}
>`
},
'
el-select
'
:
el
=>
{
const
{
disabled
,
vModel
,
clearable
,
placeholder
,
width
}
=
attrBuilder
(
el
)
const
filterable
=
el
.
filterable
?
'
filterable
'
:
''
const
multiple
=
el
.
multiple
?
'
multiple
'
:
''
let
child
=
buildElSelectChild
(
el
)
if
(
child
)
child
=
`\n
${
child
}
\n`
// 换行
return
`<
${
el
.
tag
}
${
vModel
}
${
placeholder
}
${
disabled
}
${
multiple
}
${
filterable
}
${
clearable
}
${
width
}
>
${
child
}
</
${
el
.
tag
}
>`
},
'
el-radio-group
'
:
el
=>
{
const
{
disabled
,
vModel
}
=
attrBuilder
(
el
)
const
size
=
`size="
${
el
.
size
}
"`
let
child
=
buildElRadioGroupChild
(
el
)
if
(
child
)
child
=
`\n
${
child
}
\n`
// 换行
return
`<
${
el
.
tag
}
${
vModel
}
${
size
}
${
disabled
}
>
${
child
}
</
${
el
.
tag
}
>`
},
'
el-checkbox-group
'
:
el
=>
{
const
{
disabled
,
vModel
}
=
attrBuilder
(
el
)
const
size
=
`size="
${
el
.
size
}
"`
const
min
=
el
.
min
?
`:min="
${
el
.
min
}
"`
:
''
const
max
=
el
.
max
?
`:max="
${
el
.
max
}
"`
:
''
let
child
=
buildElCheckboxGroupChild
(
el
)
if
(
child
)
child
=
`\n
${
child
}
\n`
// 换行
return
`<
${
el
.
tag
}
${
vModel
}
${
min
}
${
max
}
${
size
}
${
disabled
}
>
${
child
}
</
${
el
.
tag
}
>`
},
'
el-switch
'
:
el
=>
{
const
{
disabled
,
vModel
}
=
attrBuilder
(
el
)
const
activeText
=
el
[
'
active-text
'
]
?
`active-text="
${
el
[
'
active-text
'
]}
"`
:
''
const
inactiveText
=
el
[
'
inactive-text
'
]
?
`inactive-text="
${
el
[
'
inactive-text
'
]}
"`
:
''
const
activeColor
=
el
[
'
active-color
'
]
?
`active-color="
${
el
[
'
active-color
'
]}
"`
:
''
const
inactiveColor
=
el
[
'
inactive-color
'
]
?
`inactive-color="
${
el
[
'
inactive-color
'
]}
"`
:
''
const
activeValue
=
el
[
'
active-value
'
]
!==
true
?
`:active-value='
${
JSON
.
stringify
(
el
[
'
active-value
'
])}
'`
:
''
const
inactiveValue
=
el
[
'
inactive-value
'
]
!==
false
?
`:inactive-value='
${
JSON
.
stringify
(
el
[
'
inactive-value
'
])}
'`
:
''
return
`<
${
el
.
tag
}
${
vModel
}
${
activeText
}
${
inactiveText
}
${
activeColor
}
${
inactiveColor
}
${
activeValue
}
${
inactiveValue
}
${
disabled
}
></
${
el
.
tag
}
>`
},
'
el-cascader
'
:
el
=>
{
const
{
disabled
,
vModel
,
clearable
,
placeholder
,
width
}
=
attrBuilder
(
el
)
const
options
=
el
.
options
?
`:options="
${
el
.
vModel
}
Options"`
:
''
const
props
=
el
.
props
?
`:props="
${
el
.
vModel
}
Props"`
:
''
const
showAllLevels
=
el
[
'
show-all-levels
'
]
?
''
:
'
:show-all-levels="false"
'
const
filterable
=
el
.
filterable
?
'
filterable
'
:
''
const
separator
=
el
.
separator
===
'
/
'
?
''
:
`separator="
${
el
.
separator
}
"`
return
`<
${
el
.
tag
}
${
vModel
}
${
options
}
${
props
}
${
width
}
${
showAllLevels
}
${
placeholder
}
${
separator
}
${
filterable
}
${
clearable
}
${
disabled
}
></
${
el
.
tag
}
>`
},
'
el-slider
'
:
el
=>
{
const
{
disabled
,
vModel
}
=
attrBuilder
(
el
)
const
min
=
el
.
min
?
`:min='
${
el
.
min
}
'`
:
''
const
max
=
el
.
max
?
`:max='
${
el
.
max
}
'`
:
''
const
step
=
el
.
step
?
`:step='
${
el
.
step
}
'`
:
''
const
range
=
el
.
range
?
'
range
'
:
''
const
showStops
=
el
[
'
show-stops
'
]
?
`:show-stops="
${
el
[
'
show-stops
'
]}
"`
:
''
return
`<
${
el
.
tag
}
${
min
}
${
max
}
${
step
}
${
vModel
}
${
range
}
${
showStops
}
${
disabled
}
></
${
el
.
tag
}
>`
},
'
el-time-picker
'
:
el
=>
{
const
{
disabled
,
vModel
,
clearable
,
placeholder
,
width
}
=
attrBuilder
(
el
)
const
startPlaceholder
=
el
[
'
start-placeholder
'
]
?
`start-placeholder="
${
el
[
'
start-placeholder
'
]}
"`
:
''
const
endPlaceholder
=
el
[
'
end-placeholder
'
]
?
`end-placeholder="
${
el
[
'
end-placeholder
'
]}
"`
:
''
const
rangeSeparator
=
el
[
'
range-separator
'
]
?
`range-separator="
${
el
[
'
range-separator
'
]}
"`
:
''
const
isRange
=
el
[
'
is-range
'
]
?
'
is-range
'
:
''
const
format
=
el
.
format
?
`format="
${
el
.
format
}
"`
:
''
const
valueFormat
=
el
[
'
value-format
'
]
?
`value-format="
${
el
[
'
value-format
'
]}
"`
:
''
const
pickerOptions
=
el
[
'
picker-options
'
]
?
`:picker-options='
${
JSON
.
stringify
(
el
[
'
picker-options
'
])}
'`
:
''
return
`<
${
el
.
tag
}
${
vModel
}
${
isRange
}
${
format
}
${
valueFormat
}
${
pickerOptions
}
${
width
}
${
placeholder
}
${
startPlaceholder
}
${
endPlaceholder
}
${
rangeSeparator
}
${
clearable
}
${
disabled
}
></
${
el
.
tag
}
>`
},
'
el-date-picker
'
:
el
=>
{
const
{
disabled
,
vModel
,
clearable
,
placeholder
,
width
}
=
attrBuilder
(
el
)
const
startPlaceholder
=
el
[
'
start-placeholder
'
]
?
`start-placeholder="
${
el
[
'
start-placeholder
'
]}
"`
:
''
const
endPlaceholder
=
el
[
'
end-placeholder
'
]
?
`end-placeholder="
${
el
[
'
end-placeholder
'
]}
"`
:
''
const
rangeSeparator
=
el
[
'
range-separator
'
]
?
`range-separator="
${
el
[
'
range-separator
'
]}
"`
:
''
const
format
=
el
.
format
?
`format="
${
el
.
format
}
"`
:
''
const
valueFormat
=
el
[
'
value-format
'
]
?
`value-format="
${
el
[
'
value-format
'
]}
"`
:
''
const
type
=
el
.
type
===
'
date
'
?
''
:
`type="
${
el
.
type
}
"`
const
readonly
=
el
.
readonly
?
'
readonly
'
:
''
return
`<
${
el
.
tag
}
${
type
}
${
vModel
}
${
format
}
${
valueFormat
}
${
width
}
${
placeholder
}
${
startPlaceholder
}
${
endPlaceholder
}
${
rangeSeparator
}
${
clearable
}
${
readonly
}
${
disabled
}
></
${
el
.
tag
}
>`
},
'
el-rate
'
:
el
=>
{
const
{
disabled
,
vModel
}
=
attrBuilder
(
el
)
const
max
=
el
.
max
?
`:max='
${
el
.
max
}
'`
:
''
const
allowHalf
=
el
[
'
allow-half
'
]
?
'
allow-half
'
:
''
const
showText
=
el
[
'
show-text
'
]
?
'
show-text
'
:
''
const
showScore
=
el
[
'
show-score
'
]
?
'
show-score
'
:
''
return
`<
${
el
.
tag
}
${
vModel
}
${
allowHalf
}
${
showText
}
${
showScore
}
${
disabled
}
></
${
el
.
tag
}
>`
},
'
el-color-picker
'
:
el
=>
{
const
{
disabled
,
vModel
}
=
attrBuilder
(
el
)
const
size
=
`size="
${
el
.
size
}
"`
const
showAlpha
=
el
[
'
show-alpha
'
]
?
'
show-alpha
'
:
''
const
colorFormat
=
el
[
'
color-format
'
]
?
`color-format="
${
el
[
'
color-format
'
]}
"`
:
''
return
`<
${
el
.
tag
}
${
vModel
}
${
size
}
${
showAlpha
}
${
colorFormat
}
${
disabled
}
></
${
el
.
tag
}
>`
},
'
el-upload
'
:
el
=>
{
const
disabled
=
el
.
disabled
?
'
:disabled=
\'
true
\'
'
:
''
const
action
=
el
.
action
?
`:action="
${
el
.
vModel
}
Action"`
:
''
const
multiple
=
el
.
multiple
?
'
multiple
'
:
''
const
listType
=
el
[
'
list-type
'
]
!==
'
text
'
?
`list-type="
${
el
[
'
list-type
'
]}
"`
:
''
const
accept
=
el
.
accept
?
`accept="
${
el
.
accept
}
"`
:
''
const
name
=
el
.
name
!==
'
file
'
?
`name="
${
el
.
name
}
"`
:
''
const
autoUpload
=
el
[
'
auto-upload
'
]
===
false
?
'
:auto-upload="false"
'
:
''
const
beforeUpload
=
`:before-upload="
${
el
.
vModel
}
BeforeUpload"`
const
fileList
=
`:file-list="
${
el
.
vModel
}
fileList"`
const
ref
=
`ref="
${
el
.
vModel
}
"`
let
child
=
buildElUploadChild
(
el
)
if
(
child
)
child
=
`\n
${
child
}
\n`
// 换行
return
`<
${
el
.
tag
}
${
ref
}
${
fileList
}
${
action
}
${
autoUpload
}
${
multiple
}
${
beforeUpload
}
${
listType
}
${
accept
}
${
name
}
${
disabled
}
>
${
child
}
</
${
el
.
tag
}
>`
}
}
function
attrBuilder
(
el
)
{
return
{
vModel
:
`v-model="
${
confGlobal
.
formModel
}
.
${
el
.
vModel
}
"`
,
clearable
:
el
.
clearable
?
'
clearable
'
:
''
,
placeholder
:
el
.
placeholder
?
`placeholder="
${
el
.
placeholder
}
"`
:
''
,
width
:
el
.
style
&&
el
.
style
.
width
?
'
:style="{width:
\'
100%
\'
}"
'
:
''
,
disabled
:
el
.
disabled
?
'
:disabled=
\'
true
\'
'
:
''
}
}
// el-buttin 子级
function
buildElButtonChild
(
conf
)
{
const
children
=
[]
if
(
conf
.
default
)
{
children
.
push
(
conf
.
default
)
}
return
children
.
join
(
'
\n
'
)
}
// el-input innerHTML
function
buildElInputChild
(
conf
)
{
const
children
=
[]
if
(
conf
.
prepend
)
{
children
.
push
(
`<template slot="prepend">
${
conf
.
prepend
}
</template>`
)
}
if
(
conf
.
append
)
{
children
.
push
(
`<template slot="append">
${
conf
.
append
}
</template>`
)
}
return
children
.
join
(
'
\n
'
)
}
function
buildElSelectChild
(
conf
)
{
const
children
=
[]
if
(
conf
.
options
&&
conf
.
options
.
length
)
{
children
.
push
(
`<el-option v-for="(item, index) in
${
conf
.
vModel
}
Options" :key="index" :label="item.label" :value="item.value" :disabled="item.disabled"></el-option>`
)
}
return
children
.
join
(
'
\n
'
)
}
function
buildElRadioGroupChild
(
conf
)
{
const
children
=
[]
if
(
conf
.
options
&&
conf
.
options
.
length
)
{
const
tag
=
conf
.
optionType
===
'
button
'
?
'
el-radio-button
'
:
'
el-radio
'
const
border
=
conf
.
border
?
'
border
'
:
''
children
.
push
(
`<
${
tag
}
v-for="(item, index) in
${
conf
.
vModel
}
Options" :key="index" :label="item.value" :disabled="item.disabled"
${
border
}
>{{item.label}}</
${
tag
}
>`
)
}
return
children
.
join
(
'
\n
'
)
}
function
buildElCheckboxGroupChild
(
conf
)
{
const
children
=
[]
if
(
conf
.
options
&&
conf
.
options
.
length
)
{
const
tag
=
conf
.
optionType
===
'
button
'
?
'
el-checkbox-button
'
:
'
el-checkbox
'
const
border
=
conf
.
border
?
'
border
'
:
''
children
.
push
(
`<
${
tag
}
v-for="(item, index) in
${
conf
.
vModel
}
Options" :key="index" :label="item.value" :disabled="item.disabled"
${
border
}
>{{item.label}}</
${
tag
}
>`
)
}
return
children
.
join
(
'
\n
'
)
}
function
buildElUploadChild
(
conf
)
{
const
list
=
[]
if
(
conf
[
'
list-type
'
]
===
'
picture-card
'
)
list
.
push
(
'
<i class="el-icon-plus"></i>
'
)
else
list
.
push
(
`<el-button size="small" type="primary" icon="el-icon-upload">
${
conf
.
buttonText
}
</el-button>`
)
if
(
conf
.
showTip
)
list
.
push
(
`<div slot="tip" class="el-upload__tip">只能上传不超过
${
conf
.
fileSize
}${
conf
.
sizeUnit
}
的
${
conf
.
accept
}
文件</div>`
)
return
list
.
join
(
'
\n
'
)
}
export
function
makeUpHtml
(
conf
,
type
)
{
const
htmlList
=
[]
confGlobal
=
conf
someSpanIsNot24
=
conf
.
fields
.
some
(
item
=>
item
.
span
!==
24
)
conf
.
fields
.
forEach
(
el
=>
{
htmlList
.
push
(
layouts
[
el
.
layout
](
el
))
})
const
htmlStr
=
htmlList
.
join
(
'
\n
'
)
let
temp
=
buildFormTemplate
(
conf
,
htmlStr
,
type
)
if
(
type
===
'
dialog
'
)
{
temp
=
dialogWrapper
(
temp
)
}
confGlobal
=
null
return
temp
}
ruoyi-ui/src/utils/generator/js.js
View file @
a29201a2
import
{
isArray
}
from
'
util
'
import
{
exportDefault
,
titleCase
}
from
'
@/utils/index
'
import
{
trigger
}
from
'
./config
'
const
units
=
{
KB
:
'
1024
'
,
MB
:
'
1024 / 1024
'
,
GB
:
'
1024 / 1024 / 1024
'
}
let
confGlobal
const
inheritAttrs
=
{
file
:
''
,
dialog
:
'
inheritAttrs: false,
'
}
export
function
makeUpJs
(
conf
,
type
)
{
confGlobal
=
conf
=
JSON
.
parse
(
JSON
.
stringify
(
conf
))
const
dataList
=
[]
const
ruleList
=
[]
const
optionsList
=
[]
const
propsList
=
[]
const
methodList
=
mixinMethod
(
type
)
const
uploadVarList
=
[]
conf
.
fields
.
forEach
(
el
=>
{
buildAttributes
(
el
,
dataList
,
ruleList
,
optionsList
,
methodList
,
propsList
,
uploadVarList
)
})
const
script
=
buildexport
(
conf
,
type
,
dataList
.
join
(
'
\n
'
),
ruleList
.
join
(
'
\n
'
),
optionsList
.
join
(
'
\n
'
),
uploadVarList
.
join
(
'
\n
'
),
propsList
.
join
(
'
\n
'
),
methodList
.
join
(
'
\n
'
)
)
confGlobal
=
null
return
script
}
function
buildAttributes
(
el
,
dataList
,
ruleList
,
optionsList
,
methodList
,
propsList
,
uploadVarList
)
{
buildData
(
el
,
dataList
)
buildRules
(
el
,
ruleList
)
if
(
el
.
options
&&
el
.
options
.
length
)
{
buildOptions
(
el
,
optionsList
)
if
(
el
.
dataType
===
'
dynamic
'
)
{
const
model
=
`
${
el
.
vModel
}
Options`
const
options
=
titleCase
(
model
)
buildOptionMethod
(
`get
${
options
}
`
,
model
,
methodList
)
}
}
if
(
el
.
props
&&
el
.
props
.
props
)
{
buildProps
(
el
,
propsList
)
}
if
(
el
.
action
&&
el
.
tag
===
'
el-upload
'
)
{
uploadVarList
.
push
(
`
${
el
.
vModel
}
Action: '
${
el
.
action
}
',
${
el
.
vModel
}
fileList: [],`
)
methodList
.
push
(
buildBeforeUpload
(
el
))
if
(
!
el
[
'
auto-upload
'
])
{
methodList
.
push
(
buildSubmitUpload
(
el
))
}
}
if
(
el
.
children
)
{
el
.
children
.
forEach
(
el2
=>
{
buildAttributes
(
el2
,
dataList
,
ruleList
,
optionsList
,
methodList
,
propsList
,
uploadVarList
)
})
}
}
function
mixinMethod
(
type
)
{
const
list
=
[];
const
minxins
=
{
file
:
confGlobal
.
formBtns
?
{
submitForm
:
`submitForm() {
this.$refs['
${
confGlobal
.
formRef
}
'].validate(valid => {
if(!valid) return
// TODO 提交表单
})
},`
,
resetForm
:
`resetForm() {
this.$refs['
${
confGlobal
.
formRef
}
'].resetFields()
},`
}
:
null
,
dialog
:
{
onOpen
:
'
onOpen() {},
'
,
onClose
:
`onClose() {
this.$refs['
${
confGlobal
.
formRef
}
'].resetFields()
},`
,
close
:
`close() {
this.$emit('update:visible', false)
},`
,
hand
elConfirm
:
`handelConfirm() {
this.$refs['
${
confGlobal
.
formRef
}
'].validate(valid => {
if(!valid) return
this.close()
})
},`
}
}
const
methods
=
minxins
[
type
]
if
(
methods
)
{
Object
.
keys
(
methods
).
forEach
(
key
=>
{
list
.
push
(
methods
[
key
])
})
}
return
list
}
function
buildData
(
conf
,
dataList
)
{
if
(
conf
.
vModel
===
undefined
)
return
let
defaultValue
if
(
typeof
(
conf
.
defaultValue
)
===
'
string
'
&&
!
conf
.
multiple
)
{
defaultValue
=
`'
${
conf
.
defaultValue
}
'`
}
else
{
defaultValue
=
`
${
JSON
.
stringify
(
conf
.
defaultValue
)}
`
}
dataList
.
push
(
`
${
conf
.
vModel
}
:
${
defaultValue
}
,`
)
}
function
buildRules
(
conf
,
ruleList
)
{
if
(
conf
.
vModel
===
undefined
)
return
const
rules
=
[]
if
(
trigger
[
conf
.
tag
])
{
if
(
conf
.
required
)
{
const
type
=
isArray
(
conf
.
defaultValue
)
?
'
type:
\'
array
\'
,
'
:
''
let
message
=
isArray
(
conf
.
defaultValue
)
?
`请至少选择一个
${
conf
.
vModel
}
`
:
conf
.
placeholder
if
(
message
===
undefined
)
message
=
`
${
conf
.
label
}
不能为空`
rules
.
push
(
`{ required: true,
${
type
}
message: '
${
message
}
', trigger: '
${
trigger
[
conf
.
tag
]}
' }`
)
}
if
(
conf
.
regList
&&
isArray
(
conf
.
regList
))
{
conf
.
regList
.
forEach
(
item
=>
{
if
(
item
.
pattern
)
{
rules
.
push
(
`{ pattern:
${
eval
(
item
.
pattern
)}
, message: '
${
item
.
message
}
', trigger: '
${
trigger
[
conf
.
tag
]}
' }`
)
}
})
}
ruleList
.
push
(
`
${
conf
.
vModel
}
: [
${
rules
.
join
(
'
,
'
)}
],`
)
}
}
function
buildOptions
(
conf
,
optionsList
)
{
if
(
conf
.
vModel
===
undefined
)
return
if
(
conf
.
dataType
===
'
dynamic
'
)
{
conf
.
options
=
[]
}
const
str
=
`
${
conf
.
vModel
}
Options:
${
JSON
.
stringify
(
conf
.
options
)}
,`
optionsList
.
push
(
str
)
}
function
buildProps
(
conf
,
propsList
)
{
if
(
conf
.
dataType
===
'
dynamic
'
)
{
conf
.
valueKey
!==
'
value
'
&&
(
conf
.
props
.
props
.
value
=
conf
.
valueKey
)
conf
.
labelKey
!==
'
label
'
&&
(
conf
.
props
.
props
.
label
=
conf
.
labelKey
)
conf
.
childrenKey
!==
'
children
'
&&
(
conf
.
props
.
props
.
children
=
conf
.
childrenKey
)
}
const
str
=
`
${
conf
.
vModel
}
Props:
${
JSON
.
stringify
(
conf
.
props
.
props
)}
,`
propsList
.
push
(
str
)
}
function
buildBeforeUpload
(
conf
)
{
const
unitNum
=
units
[
conf
.
sizeUnit
];
let
rightSizeCode
=
''
;
let
acceptCode
=
''
;
const
returnList
=
[]
if
(
conf
.
fileSize
)
{
rightSizeCode
=
`let isRightSize = file.size /
${
unitNum
}
<
${
conf
.
fileSize
}
if(!isRightSize){
this.$message.error('文件大小超过
${
conf
.
fileSize
}${
conf
.
sizeUnit
}
')
}`
returnList
.
push
(
'
isRightSize
'
)
}
if
(
conf
.
accept
)
{
acceptCode
=
`let isAccept = new RegExp('
${
conf
.
accept
}
').test(file.type)
if(!isAccept){
this.$message.error('应该选择
${
conf
.
accept
}
类型的文件')
}`
returnList
.
push
(
'
isAccept
'
)
}
const
str
=
`
${
conf
.
vModel
}
BeforeUpload(file) {
${
rightSizeCode
}
${
acceptCode
}
return
${
returnList
.
join
(
'
&&
'
)}
},`
return
returnList
.
length
?
str
:
''
}
function
buildSubmitUpload
(
conf
)
{
const
str
=
`submitUpload() {
this.$refs['
${
conf
.
vModel
}
'].submit()
},`
return
str
}
function
buildOptionMethod
(
methodName
,
model
,
methodList
)
{
const
str
=
`
${
methodName
}
() {
// TODO 发起请求获取数据
this.
${
model
}
},`
methodList
.
push
(
str
)
}
function
buildexport
(
conf
,
type
,
data
,
rules
,
selectOptions
,
uploadVar
,
props
,
methods
)
{
const
str
=
`
${
exportDefault
}
{
${
inheritAttrs
[
type
]}
components: {},
props: [],
data () {
return {
${
conf
.
formModel
}
: {
${
data
}
},
${
conf
.
formRules
}
: {
${
rules
}
},
${
uploadVar
}
${
selectOptions
}
${
props
}
}
},
computed: {},
watch: {},
created () {},
mounted () {},
methods: {
${
methods
}
}
}`
return
str
}
import
{
isArray
}
from
'
util
'
import
{
exportDefault
,
titleCase
}
from
'
@/utils/index
'
import
{
trigger
}
from
'
./config
'
const
units
=
{
KB
:
'
1024
'
,
MB
:
'
1024 / 1024
'
,
GB
:
'
1024 / 1024 / 1024
'
}
let
confGlobal
const
inheritAttrs
=
{
file
:
''
,
dialog
:
'
inheritAttrs: false,
'
}
export
function
makeUpJs
(
conf
,
type
)
{
confGlobal
=
conf
=
JSON
.
parse
(
JSON
.
stringify
(
conf
))
const
dataList
=
[]
const
ruleList
=
[]
const
optionsList
=
[]
const
propsList
=
[]
const
methodList
=
mixinMethod
(
type
)
const
uploadVarList
=
[]
conf
.
fields
.
forEach
(
el
=>
{
buildAttributes
(
el
,
dataList
,
ruleList
,
optionsList
,
methodList
,
propsList
,
uploadVarList
)
})
const
script
=
buildexport
(
conf
,
type
,
dataList
.
join
(
'
\n
'
),
ruleList
.
join
(
'
\n
'
),
optionsList
.
join
(
'
\n
'
),
uploadVarList
.
join
(
'
\n
'
),
propsList
.
join
(
'
\n
'
),
methodList
.
join
(
'
\n
'
)
)
confGlobal
=
null
return
script
}
function
buildAttributes
(
el
,
dataList
,
ruleList
,
optionsList
,
methodList
,
propsList
,
uploadVarList
)
{
buildData
(
el
,
dataList
)
buildRules
(
el
,
ruleList
)
if
(
el
.
options
&&
el
.
options
.
length
)
{
buildOptions
(
el
,
optionsList
)
if
(
el
.
dataType
===
'
dynamic
'
)
{
const
model
=
`
${
el
.
vModel
}
Options`
const
options
=
titleCase
(
model
)
buildOptionMethod
(
`get
${
options
}
`
,
model
,
methodList
)
}
}
if
(
el
.
props
&&
el
.
props
.
props
)
{
buildProps
(
el
,
propsList
)
}
if
(
el
.
action
&&
el
.
tag
===
'
el-upload
'
)
{
uploadVarList
.
push
(
`
${
el
.
vModel
}
Action: '
${
el
.
action
}
',
${
el
.
vModel
}
fileList: [],`
)
methodList
.
push
(
buildBeforeUpload
(
el
))
if
(
!
el
[
'
auto-upload
'
])
{
methodList
.
push
(
buildSubmitUpload
(
el
))
}
}
if
(
el
.
children
)
{
el
.
children
.
forEach
(
el2
=>
{
buildAttributes
(
el2
,
dataList
,
ruleList
,
optionsList
,
methodList
,
propsList
,
uploadVarList
)
})
}
}
function
mixinMethod
(
type
)
{
const
list
=
[];
const
minxins
=
{
file
:
confGlobal
.
formBtns
?
{
submitForm
:
`submitForm() {
this.$refs['
${
confGlobal
.
formRef
}
'].validate(valid => {
if(!valid) return
// TODO 提交表单
})
},`
,
resetForm
:
`resetForm() {
this.$refs['
${
confGlobal
.
formRef
}
'].resetFields()
},`
}
:
null
,
dialog
:
{
onOpen
:
'
onOpen() {},
'
,
onClose
:
`onClose() {
this.$refs['
${
confGlobal
.
formRef
}
'].resetFields()
},`
,
close
:
`close() {
this.$emit('update:visible', false)
},`
,
hand
leConfirm
:
`handleConfirm() {
this.$refs['
${
confGlobal
.
formRef
}
'].validate(valid => {
if(!valid) return
this.close()
})
},`
}
}
const
methods
=
minxins
[
type
]
if
(
methods
)
{
Object
.
keys
(
methods
).
forEach
(
key
=>
{
list
.
push
(
methods
[
key
])
})
}
return
list
}
function
buildData
(
conf
,
dataList
)
{
if
(
conf
.
vModel
===
undefined
)
return
let
defaultValue
if
(
typeof
(
conf
.
defaultValue
)
===
'
string
'
&&
!
conf
.
multiple
)
{
defaultValue
=
`'
${
conf
.
defaultValue
}
'`
}
else
{
defaultValue
=
`
${
JSON
.
stringify
(
conf
.
defaultValue
)}
`
}
dataList
.
push
(
`
${
conf
.
vModel
}
:
${
defaultValue
}
,`
)
}
function
buildRules
(
conf
,
ruleList
)
{
if
(
conf
.
vModel
===
undefined
)
return
const
rules
=
[]
if
(
trigger
[
conf
.
tag
])
{
if
(
conf
.
required
)
{
const
type
=
isArray
(
conf
.
defaultValue
)
?
'
type:
\'
array
\'
,
'
:
''
let
message
=
isArray
(
conf
.
defaultValue
)
?
`请至少选择一个
${
conf
.
vModel
}
`
:
conf
.
placeholder
if
(
message
===
undefined
)
message
=
`
${
conf
.
label
}
不能为空`
rules
.
push
(
`{ required: true,
${
type
}
message: '
${
message
}
', trigger: '
${
trigger
[
conf
.
tag
]}
' }`
)
}
if
(
conf
.
regList
&&
isArray
(
conf
.
regList
))
{
conf
.
regList
.
forEach
(
item
=>
{
if
(
item
.
pattern
)
{
rules
.
push
(
`{ pattern:
${
eval
(
item
.
pattern
)}
, message: '
${
item
.
message
}
', trigger: '
${
trigger
[
conf
.
tag
]}
' }`
)
}
})
}
ruleList
.
push
(
`
${
conf
.
vModel
}
: [
${
rules
.
join
(
'
,
'
)}
],`
)
}
}
function
buildOptions
(
conf
,
optionsList
)
{
if
(
conf
.
vModel
===
undefined
)
return
if
(
conf
.
dataType
===
'
dynamic
'
)
{
conf
.
options
=
[]
}
const
str
=
`
${
conf
.
vModel
}
Options:
${
JSON
.
stringify
(
conf
.
options
)}
,`
optionsList
.
push
(
str
)
}
function
buildProps
(
conf
,
propsList
)
{
if
(
conf
.
dataType
===
'
dynamic
'
)
{
conf
.
valueKey
!==
'
value
'
&&
(
conf
.
props
.
props
.
value
=
conf
.
valueKey
)
conf
.
labelKey
!==
'
label
'
&&
(
conf
.
props
.
props
.
label
=
conf
.
labelKey
)
conf
.
childrenKey
!==
'
children
'
&&
(
conf
.
props
.
props
.
children
=
conf
.
childrenKey
)
}
const
str
=
`
${
conf
.
vModel
}
Props:
${
JSON
.
stringify
(
conf
.
props
.
props
)}
,`
propsList
.
push
(
str
)
}
function
buildBeforeUpload
(
conf
)
{
const
unitNum
=
units
[
conf
.
sizeUnit
];
let
rightSizeCode
=
''
;
let
acceptCode
=
''
;
const
returnList
=
[]
if
(
conf
.
fileSize
)
{
rightSizeCode
=
`let isRightSize = file.size /
${
unitNum
}
<
${
conf
.
fileSize
}
if(!isRightSize){
this.$message.error('文件大小超过
${
conf
.
fileSize
}${
conf
.
sizeUnit
}
')
}`
returnList
.
push
(
'
isRightSize
'
)
}
if
(
conf
.
accept
)
{
acceptCode
=
`let isAccept = new RegExp('
${
conf
.
accept
}
').test(file.type)
if(!isAccept){
this.$message.error('应该选择
${
conf
.
accept
}
类型的文件')
}`
returnList
.
push
(
'
isAccept
'
)
}
const
str
=
`
${
conf
.
vModel
}
BeforeUpload(file) {
${
rightSizeCode
}
${
acceptCode
}
return
${
returnList
.
join
(
'
&&
'
)}
},`
return
returnList
.
length
?
str
:
''
}
function
buildSubmitUpload
(
conf
)
{
const
str
=
`submitUpload() {
this.$refs['
${
conf
.
vModel
}
'].submit()
},`
return
str
}
function
buildOptionMethod
(
methodName
,
model
,
methodList
)
{
const
str
=
`
${
methodName
}
() {
// TODO 发起请求获取数据
this.
${
model
}
},`
methodList
.
push
(
str
)
}
function
buildexport
(
conf
,
type
,
data
,
rules
,
selectOptions
,
uploadVar
,
props
,
methods
)
{
const
str
=
`
${
exportDefault
}
{
${
inheritAttrs
[
type
]}
components: {},
props: [],
data () {
return {
${
conf
.
formModel
}
: {
${
data
}
},
${
conf
.
formRules
}
: {
${
rules
}
},
${
uploadVar
}
${
selectOptions
}
${
props
}
}
},
computed: {},
watch: {},
created () {},
mounted () {},
methods: {
${
methods
}
}
}`
return
str
}
ruoyi-ui/src/views/tool/build/CodeTypeDialog.vue
View file @
a29201a2
<
template
>
<div>
<el-dialog
v-bind=
"$attrs"
width=
"500px"
:close-on-click-modal=
"false"
:modal-append-to-body=
"false"
v-on=
"$listeners"
@
open=
"onOpen"
@
close=
"onClose"
>
<el-row
:gutter=
"15"
>
<el-form
ref=
"elForm"
:model=
"formData"
:rules=
"rules"
size=
"medium"
label-width=
"100px"
>
<el-col
:span=
"24"
>
<el-form-item
label=
"生成类型"
prop=
"type"
>
<el-radio-group
v-model=
"formData.type"
>
<el-radio-button
v-for=
"(item, index) in typeOptions"
:key=
"index"
:label=
"item.value"
:disabled=
"item.disabled"
>
{{
item
.
label
}}
</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item
v-if=
"showFileName"
label=
"文件名"
prop=
"fileName"
>
<el-input
v-model=
"formData.fileName"
placeholder=
"请输入文件名"
clearable
/>
</el-form-item>
</el-col>
</el-form>
</el-row>
<div
slot=
"footer"
>
<el-button
@
click=
"close"
>
取消
</el-button>
<el-button
type=
"primary"
@
click=
"hand
elConfirm"
>
确定
</el-button>
</div>
</el-dialog>
</div>
</
template
>
<
script
>
export
default
{
inheritAttrs
:
false
,
props
:
[
'
showFileName
'
],
data
()
{
return
{
formData
:
{
fileName
:
undefined
,
type
:
'
file
'
},
rules
:
{
fileName
:
[{
required
:
true
,
message
:
'
请输入文件名
'
,
trigger
:
'
blur
'
}],
type
:
[{
required
:
true
,
message
:
'
生成类型不能为空
'
,
trigger
:
'
change
'
}]
},
typeOptions
:
[{
label
:
'
页面
'
,
value
:
'
file
'
},
{
label
:
'
弹窗
'
,
value
:
'
dialog
'
}]
}
},
computed
:
{
},
watch
:
{},
mounted
()
{},
methods
:
{
onOpen
()
{
if
(
this
.
showFileName
)
{
this
.
formData
.
fileName
=
`
${
+
new
Date
()}
.vue`
}
},
onClose
()
{
},
close
(
e
)
{
this
.
$emit
(
'
update:visible
'
,
false
)
},
hand
elConfirm
()
{
this
.
$refs
.
elForm
.
validate
(
valid
=>
{
if
(
!
valid
)
return
this
.
$emit
(
'
confirm
'
,
{
...
this
.
formData
})
this
.
close
()
})
}
}
}
</
script
>
<
template
>
<div>
<el-dialog
v-bind=
"$attrs"
width=
"500px"
:close-on-click-modal=
"false"
:modal-append-to-body=
"false"
v-on=
"$listeners"
@
open=
"onOpen"
@
close=
"onClose"
>
<el-row
:gutter=
"15"
>
<el-form
ref=
"elForm"
:model=
"formData"
:rules=
"rules"
size=
"medium"
label-width=
"100px"
>
<el-col
:span=
"24"
>
<el-form-item
label=
"生成类型"
prop=
"type"
>
<el-radio-group
v-model=
"formData.type"
>
<el-radio-button
v-for=
"(item, index) in typeOptions"
:key=
"index"
:label=
"item.value"
:disabled=
"item.disabled"
>
{{
item
.
label
}}
</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item
v-if=
"showFileName"
label=
"文件名"
prop=
"fileName"
>
<el-input
v-model=
"formData.fileName"
placeholder=
"请输入文件名"
clearable
/>
</el-form-item>
</el-col>
</el-form>
</el-row>
<div
slot=
"footer"
>
<el-button
@
click=
"close"
>
取消
</el-button>
<el-button
type=
"primary"
@
click=
"hand
leConfirm"
>
确定
</el-button>
</div>
</el-dialog>
</div>
</
template
>
<
script
>
export
default
{
inheritAttrs
:
false
,
props
:
[
'
showFileName
'
],
data
()
{
return
{
formData
:
{
fileName
:
undefined
,
type
:
'
file
'
},
rules
:
{
fileName
:
[{
required
:
true
,
message
:
'
请输入文件名
'
,
trigger
:
'
blur
'
}],
type
:
[{
required
:
true
,
message
:
'
生成类型不能为空
'
,
trigger
:
'
change
'
}]
},
typeOptions
:
[{
label
:
'
页面
'
,
value
:
'
file
'
},
{
label
:
'
弹窗
'
,
value
:
'
dialog
'
}]
}
},
computed
:
{
},
watch
:
{},
mounted
()
{},
methods
:
{
onOpen
()
{
if
(
this
.
showFileName
)
{
this
.
formData
.
fileName
=
`
${
+
new
Date
()}
.vue`
}
},
onClose
()
{
},
close
(
e
)
{
this
.
$emit
(
'
update:visible
'
,
false
)
},
hand
leConfirm
()
{
this
.
$refs
.
elForm
.
validate
(
valid
=>
{
if
(
!
valid
)
return
this
.
$emit
(
'
confirm
'
,
{
...
this
.
formData
})
this
.
close
()
})
}
}
}
</
script
>
ruoyi-ui/src/views/tool/build/TreeNodeDialog.vue
View file @
a29201a2
<
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=
"hand
elConfirm"
>
确定
</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
)
},
hand
elConfirm
()
{
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
>
<
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=
"hand
leConfirm"
>
确定
</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
)
},
hand
leConfirm
()
{
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 @
a29201a2
<
template
>
<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
>
<
script
>
import
draggable
from
'
vuedraggable
'
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
{
beautifierConf
,
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
drawingDefa
lut
from
'
@/utils/generator/drawingDefalut
'
import
logo
from
'
@/assets/logo/logo.png
'
import
CodeTypeDialog
from
'
./CodeTypeDialog
'
import
DraggableItem
from
'
./DraggableItem
'
let
oldActiveId
let
tempActiveData
export
default
{
components
:
{
draggable
,
render
,
RightPanel
,
CodeTypeDialog
,
DraggableItem
},
data
()
{
return
{
logo
,
idGlobal
:
100
,
formConf
,
inputComponents
,
selectComponents
,
layoutComponents
,
labelWidth
:
100
,
drawingList
:
drawingDefa
lut
,
drawingData
:
{},
activeId
:
drawingDefa
lut
[
0
].
formId
,
drawerVisible
:
false
,
formData
:
{},
dialogVisible
:
false
,
generateConf
:
null
,
showFileName
:
false
,
activeData
:
drawingDefa
lut
[
0
]
}
},
created
()
{
// 防止 firefox 下 拖拽 会新打卡一个选项卡
document
.
body
.
ondrop
=
event
=>
{
event
.
preventDefault
()
event
.
stopPropagation
()
}
},
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
'
})
this
.
$download
.
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
;
}
}
.left-scrollbar
.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
;
}
}
.left-scrollbar
.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
>
<
template
>
<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
>
<
script
>
import
draggable
from
'
vuedraggable
'
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
{
beautifierConf
,
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
drawingDefa
ult
from
'
@/utils/generator/drawingDefault
'
import
logo
from
'
@/assets/logo/logo.png
'
import
CodeTypeDialog
from
'
./CodeTypeDialog
'
import
DraggableItem
from
'
./DraggableItem
'
let
oldActiveId
let
tempActiveData
export
default
{
components
:
{
draggable
,
render
,
RightPanel
,
CodeTypeDialog
,
DraggableItem
},
data
()
{
return
{
logo
,
idGlobal
:
100
,
formConf
,
inputComponents
,
selectComponents
,
layoutComponents
,
labelWidth
:
100
,
drawingList
:
drawingDefa
ult
,
drawingData
:
{},
activeId
:
drawingDefa
ult
[
0
].
formId
,
drawerVisible
:
false
,
formData
:
{},
dialogVisible
:
false
,
generateConf
:
null
,
showFileName
:
false
,
activeData
:
drawingDefa
ult
[
0
]
}
},
created
()
{
// 防止 firefox 下 拖拽 会新打卡一个选项卡
document
.
body
.
ondrop
=
event
=>
{
event
.
preventDefault
()
event
.
stopPropagation
()
}
},
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
'
})
this
.
$download
.
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
;
}
}
.left-scrollbar
.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
;
}
}
.left-scrollbar
.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
>
Write
Preview
Markdown
is supported
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