Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
S
sts网站
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
liyang
sts网站
Commits
a29201a2
Commit
a29201a2
authored
Feb 09, 2022
by
稚屿
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
修正单词拼写错误
parent
612c4293
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
1662 additions
and
1662 deletions
+1662
-1662
drawingDefault.js
ruoyi-ui/src/utils/generator/drawingDefault.js
+29
-29
html.js
ruoyi-ui/src/utils/generator/html.js
+359
-359
js.js
ruoyi-ui/src/utils/generator/js.js
+236
-236
CodeTypeDialog.vue
ruoyi-ui/src/views/tool/build/CodeTypeDialog.vue
+106
-106
TreeNodeDialog.vue
ruoyi-ui/src/views/tool/build/TreeNodeDialog.vue
+149
-149
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