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
d00dc3b0
Commit
d00dc3b0
authored
Feb 12, 2022
by
若依
Committed by
Gitee
Feb 12, 2022
Browse files
Options
Browse Files
Download
Plain Diff
!426 修正单词拼写错误
Merge pull request !426 from 稚屿/master
parents
f5c69bae
c99eb980
Changes
22
Hide whitespace changes
Inline
Side-by-side
Showing
22 changed files
with
1699 additions
and
1719 deletions
+1699
-1719
ruoyi-common/src/main/java/com/ruoyi/common/utils/DictUtils.java
...ommon/src/main/java/com/ruoyi/common/utils/DictUtils.java
+1
-2
ruoyi-common/src/main/java/com/ruoyi/common/utils/ExceptionUtil.java
...n/src/main/java/com/ruoyi/common/utils/ExceptionUtil.java
+1
-2
ruoyi-common/src/main/java/com/ruoyi/common/utils/ServletUtils.java
...on/src/main/java/com/ruoyi/common/utils/ServletUtils.java
+4
-10
ruoyi-common/src/main/java/com/ruoyi/common/utils/VerifyCodeUtils.java
...src/main/java/com/ruoyi/common/utils/VerifyCodeUtils.java
+3
-8
ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUploadUtils.java
...ain/java/com/ruoyi/common/utils/file/FileUploadUtils.java
+7
-7
ruoyi-common/src/main/java/com/ruoyi/common/utils/file/ImageUtils.java
...src/main/java/com/ruoyi/common/utils/file/ImageUtils.java
+1
-1
ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpHelper.java
...src/main/java/com/ruoyi/common/utils/http/HttpHelper.java
+2
-1
ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpUtils.java
.../src/main/java/com/ruoyi/common/utils/http/HttpUtils.java
+5
-5
ruoyi-common/src/main/java/com/ruoyi/common/utils/ip/AddressUtils.java
...src/main/java/com/ruoyi/common/utils/ip/AddressUtils.java
+1
-2
ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java
...n/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java
+2
-2
ruoyi-common/src/main/java/com/ruoyi/common/utils/sign/Md5Utils.java
...n/src/main/java/com/ruoyi/common/utils/sign/Md5Utils.java
+2
-1
ruoyi-common/src/main/java/com/ruoyi/common/utils/sql/SqlUtil.java
...mon/src/main/java/com/ruoyi/common/utils/sql/SqlUtil.java
+2
-4
ruoyi-generator/src/main/java/com/ruoyi/generator/util/GenUtils.java
...ator/src/main/java/com/ruoyi/generator/util/GenUtils.java
+2
-4
ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityUtils.java
...src/main/java/com/ruoyi/generator/util/VelocityUtils.java
+1
-2
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDeptServiceImpl.java
...ava/com/ruoyi/system/service/impl/SysDeptServiceImpl.java
+2
-5
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java
...ava/com/ruoyi/system/service/impl/SysMenuServiceImpl.java
+1
-1
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-common/src/main/java/com/ruoyi/common/utils/DictUtils.java
View file @
d00dc3b0
...
...
@@ -41,8 +41,7 @@ public class DictUtils
Object
cacheObj
=
SpringUtils
.
getBean
(
RedisCache
.
class
).
getCacheObject
(
getCacheKey
(
key
));
if
(
StringUtils
.
isNotNull
(
cacheObj
))
{
List
<
SysDictData
>
dictDatas
=
StringUtils
.
cast
(
cacheObj
);
return
dictDatas
;
return
StringUtils
.
cast
(
cacheObj
);
}
return
null
;
}
...
...
ruoyi-common/src/main/java/com/ruoyi/common/utils/ExceptionUtil.java
View file @
d00dc3b0
...
...
@@ -18,8 +18,7 @@ public class ExceptionUtil
{
StringWriter
sw
=
new
StringWriter
();
e
.
printStackTrace
(
new
PrintWriter
(
sw
,
true
));
String
str
=
sw
.
toString
();
return
str
;
return
sw
.
toString
();
}
public
static
String
getRootErrorMessage
(
Exception
e
)
...
...
ruoyi-common/src/main/java/com/ruoyi/common/utils/ServletUtils.java
View file @
d00dc3b0
...
...
@@ -99,9 +99,8 @@ public class ServletUtils
*
* @param response 渲染对象
* @param string 待渲染的字符串
* @return null
*/
public
static
String
renderString
(
HttpServletResponse
response
,
String
string
)
public
static
void
renderString
(
HttpServletResponse
response
,
String
string
)
{
try
{
...
...
@@ -114,7 +113,6 @@ public class ServletUtils
{
e
.
printStackTrace
();
}
return
null
;
}
/**
...
...
@@ -125,13 +123,13 @@ public class ServletUtils
public
static
boolean
isAjaxRequest
(
HttpServletRequest
request
)
{
String
accept
=
request
.
getHeader
(
"accept"
);
if
(
accept
!=
null
&&
accept
.
indexOf
(
"application/json"
)
!=
-
1
)
if
(
accept
!=
null
&&
accept
.
contains
(
"application/json"
)
)
{
return
true
;
}
String
xRequestedWith
=
request
.
getHeader
(
"X-Requested-With"
);
if
(
xRequestedWith
!=
null
&&
xRequestedWith
.
indexOf
(
"XMLHttpRequest"
)
!=
-
1
)
if
(
xRequestedWith
!=
null
&&
xRequestedWith
.
contains
(
"XMLHttpRequest"
)
)
{
return
true
;
}
...
...
@@ -143,10 +141,6 @@ public class ServletUtils
}
String
ajax
=
request
.
getParameter
(
"__ajax"
);
if
(
StringUtils
.
inStringIgnoreCase
(
ajax
,
"json"
,
"xml"
))
{
return
true
;
}
return
false
;
return
StringUtils
.
inStringIgnoreCase
(
ajax
,
"json"
,
"xml"
);
}
}
ruoyi-common/src/main/java/com/ruoyi/common/utils/VerifyCodeUtils.java
View file @
d00dc3b0
...
...
@@ -208,7 +208,6 @@ public class VerifyCodeUtils
int
period
=
random
.
nextInt
(
40
)
+
10
;
// 50;
boolean
borderGap
=
true
;
int
frames
=
20
;
int
phase
=
7
;
for
(
int
i
=
0
;
i
<
w1
;
i
++)
...
...
@@ -216,13 +215,9 @@ public class VerifyCodeUtils
double
d
=
(
double
)
(
period
>>
1
)
*
Math
.
sin
((
double
)
i
/
(
double
)
period
+
(
6.2831853071795862
D
*
(
double
)
phase
)
/
(
double
)
frames
);
g
.
copyArea
(
i
,
0
,
1
,
h1
,
0
,
(
int
)
d
);
if
(
borderGap
)
{
g
.
setColor
(
color
);
g
.
drawLine
(
i
,
(
int
)
d
,
i
,
0
);
g
.
drawLine
(
i
,
(
int
)
d
+
h1
,
i
,
h1
);
}
g
.
setColor
(
color
);
g
.
drawLine
(
i
,
(
int
)
d
,
i
,
0
);
g
.
drawLine
(
i
,
(
int
)
d
+
h1
,
i
,
h1
);
}
}
}
\ No newline at end of file
ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUploadUtils.java
View file @
d00dc3b0
...
...
@@ -2,6 +2,8 @@ package com.ruoyi.common.utils.file;
import
java.io.File
;
import
java.io.IOException
;
import
java.util.Objects
;
import
org.apache.commons.io.FilenameUtils
;
import
org.springframework.web.multipart.MultipartFile
;
import
com.ruoyi.common.config.RuoYiConfig
;
...
...
@@ -100,7 +102,7 @@ public class FileUploadUtils
throws
FileSizeLimitExceededException
,
IOException
,
FileNameLengthLimitExceededException
,
InvalidExtensionException
{
int
fileNamelength
=
file
.
getOriginalFilename
(
).
length
();
int
fileNamelength
=
Objects
.
requireNonNull
(
file
.
getOriginalFilename
()
).
length
();
if
(
fileNamelength
>
FileUploadUtils
.
DEFAULT_FILE_NAME_LENGTH
)
{
throw
new
FileNameLengthLimitExceededException
(
FileUploadUtils
.
DEFAULT_FILE_NAME_LENGTH
);
...
...
@@ -112,8 +114,7 @@ public class FileUploadUtils
File
desc
=
getAbsoluteFile
(
baseDir
,
fileName
);
file
.
transferTo
(
desc
);
String
pathFileName
=
getPathFileName
(
baseDir
,
fileName
);
return
pathFileName
;
return
getPathFileName
(
baseDir
,
fileName
);
}
/**
...
...
@@ -145,8 +146,7 @@ public class FileUploadUtils
{
int
dirLastIndex
=
RuoYiConfig
.
getProfile
().
length
()
+
1
;
String
currentDir
=
StringUtils
.
substring
(
uploadDir
,
dirLastIndex
);
String
pathFileName
=
Constants
.
RESOURCE_PREFIX
+
"/"
+
currentDir
+
"/"
+
fileName
;
return
pathFileName
;
return
Constants
.
RESOURCE_PREFIX
+
"/"
+
currentDir
+
"/"
+
fileName
;
}
/**
...
...
@@ -161,7 +161,7 @@ public class FileUploadUtils
throws
FileSizeLimitExceededException
,
InvalidExtensionException
{
long
size
=
file
.
getSize
();
if
(
DEFAULT_MAX_SIZE
!=
-
1
&&
size
>
DEFAULT_MAX_SIZE
)
if
(
size
>
DEFAULT_MAX_SIZE
)
{
throw
new
FileSizeLimitExceededException
(
DEFAULT_MAX_SIZE
/
1024
/
1024
);
}
...
...
@@ -228,7 +228,7 @@ public class FileUploadUtils
String
extension
=
FilenameUtils
.
getExtension
(
file
.
getOriginalFilename
());
if
(
StringUtils
.
isEmpty
(
extension
))
{
extension
=
MimeTypeUtils
.
getExtension
(
file
.
getContentType
(
));
extension
=
MimeTypeUtils
.
getExtension
(
Objects
.
requireNonNull
(
file
.
getContentType
()
));
}
return
extension
;
}
...
...
ruoyi-common/src/main/java/com/ruoyi/common/utils/file/ImageUtils.java
View file @
d00dc3b0
...
...
@@ -59,7 +59,7 @@ public class ImageUtils
/**
* 读取文件为字节数据
*
* @param
key
地址
* @param
url
地址
* @return 字节数据
*/
public
static
byte
[]
readFile
(
String
url
)
...
...
ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpHelper.java
View file @
d00dc3b0
...
...
@@ -5,6 +5,7 @@ import java.io.IOException;
import
java.io.InputStream
;
import
java.io.InputStreamReader
;
import
java.nio.charset.Charset
;
import
java.nio.charset.StandardCharsets
;
import
javax.servlet.ServletRequest
;
import
org.apache.commons.lang3.exception.ExceptionUtils
;
import
org.slf4j.Logger
;
...
...
@@ -25,7 +26,7 @@ public class HttpHelper
BufferedReader
reader
=
null
;
try
(
InputStream
inputStream
=
request
.
getInputStream
())
{
reader
=
new
BufferedReader
(
new
InputStreamReader
(
inputStream
,
Charset
.
forName
(
"UTF-8"
)
));
reader
=
new
BufferedReader
(
new
InputStreamReader
(
inputStream
,
StandardCharsets
.
UTF_8
));
String
line
=
""
;
while
((
line
=
reader
.
readLine
())
!=
null
)
{
...
...
ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpUtils.java
View file @
d00dc3b0
...
...
@@ -9,6 +9,7 @@ import java.net.ConnectException;
import
java.net.SocketTimeoutException
;
import
java.net.URL
;
import
java.net.URLConnection
;
import
java.nio.charset.StandardCharsets
;
import
java.security.cert.X509Certificate
;
import
javax.net.ssl.HostnameVerifier
;
import
javax.net.ssl.HttpsURLConnection
;
...
...
@@ -130,9 +131,8 @@ public class HttpUtils
StringBuilder
result
=
new
StringBuilder
();
try
{
String
urlNameString
=
url
;
log
.
info
(
"sendPost - {}"
,
urlNameString
);
URL
realUrl
=
new
URL
(
urlNameString
);
log
.
info
(
"sendPost - {}"
,
url
);
URL
realUrl
=
new
URL
(
url
);
URLConnection
conn
=
realUrl
.
openConnection
();
conn
.
setRequestProperty
(
"accept"
,
"*/*"
);
conn
.
setRequestProperty
(
"connection"
,
"Keep-Alive"
);
...
...
@@ -144,7 +144,7 @@ public class HttpUtils
out
=
new
PrintWriter
(
conn
.
getOutputStream
());
out
.
print
(
param
);
out
.
flush
();
in
=
new
BufferedReader
(
new
InputStreamReader
(
conn
.
getInputStream
(),
"utf-8"
));
in
=
new
BufferedReader
(
new
InputStreamReader
(
conn
.
getInputStream
(),
StandardCharsets
.
UTF_8
));
String
line
;
while
((
line
=
in
.
readLine
())
!=
null
)
{
...
...
@@ -218,7 +218,7 @@ public class HttpUtils
{
if
(
ret
!=
null
&&
!
""
.
equals
(
ret
.
trim
()))
{
result
.
append
(
new
String
(
ret
.
getBytes
(
"ISO-8859-1"
),
"utf-8"
));
result
.
append
(
new
String
(
ret
.
getBytes
(
StandardCharsets
.
ISO_8859_1
),
StandardCharsets
.
UTF_8
));
}
}
log
.
info
(
"recv - {}"
,
result
);
...
...
ruoyi-common/src/main/java/com/ruoyi/common/utils/ip/AddressUtils.java
View file @
d00dc3b0
...
...
@@ -25,7 +25,6 @@ public class AddressUtils
public
static
String
getRealAddressByIP
(
String
ip
)
{
String
address
=
UNKNOWN
;
// 内网不查询
if
(
IpUtils
.
internalIp
(
ip
))
{
...
...
@@ -51,6 +50,6 @@ public class AddressUtils
log
.
error
(
"获取地理位置异常 {}"
,
ip
);
}
}
return
address
;
return
UNKNOWN
;
}
}
ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java
View file @
d00dc3b0
...
...
@@ -1121,7 +1121,7 @@ public class ExcelUtil<T>
if
(
StringUtils
.
isNotEmpty
(
excel
.
targetAttr
()))
{
String
target
=
excel
.
targetAttr
();
if
(
target
.
indexOf
(
"."
)
>
-
1
)
if
(
target
.
contains
(
"."
)
)
{
String
[]
targets
=
target
.
split
(
"[.]"
);
for
(
String
name
:
targets
)
...
...
@@ -1216,7 +1216,7 @@ public class ExcelUtil<T>
for
(
Object
[]
os
:
this
.
fields
)
{
Excel
excel
=
(
Excel
)
os
[
1
];
maxHeight
=
maxHeight
>
excel
.
height
()
?
maxHeight
:
excel
.
height
(
);
maxHeight
=
Math
.
max
(
maxHeight
,
excel
.
height
()
);
}
return
(
short
)
(
maxHeight
*
20
);
}
...
...
ruoyi-common/src/main/java/com/ruoyi/common/utils/sign/Md5Utils.java
View file @
d00dc3b0
package
com.ruoyi.common.utils.sign
;
import
java.nio.charset.StandardCharsets
;
import
java.security.MessageDigest
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
...
...
@@ -55,7 +56,7 @@ public class Md5Utils
{
try
{
return
new
String
(
toHex
(
md5
(
s
)).
getBytes
(
"UTF-8"
),
"UTF-8"
);
return
new
String
(
toHex
(
md5
(
s
)).
getBytes
(
StandardCharsets
.
UTF_8
),
StandardCharsets
.
UTF_8
);
}
catch
(
Exception
e
)
{
...
...
ruoyi-common/src/main/java/com/ruoyi/common/utils/sql/SqlUtil.java
View file @
d00dc3b0
...
...
@@ -50,10 +50,8 @@ public class SqlUtil
return
;
}
String
[]
sqlKeywords
=
StringUtils
.
split
(
SQL_REGEX
,
"\\|"
);
for
(
int
i
=
0
;
i
<
sqlKeywords
.
length
;
i
++)
{
if
(
StringUtils
.
indexOfIgnoreCase
(
value
,
sqlKeywords
[
i
])
>
-
1
)
{
for
(
String
sqlKeyword
:
sqlKeywords
)
{
if
(
StringUtils
.
indexOfIgnoreCase
(
value
,
sqlKeyword
)
>
-
1
)
{
throw
new
UtilException
(
"参数存在SQL注入风险"
);
}
}
...
...
ruoyi-generator/src/main/java/com/ruoyi/generator/util/GenUtils.java
View file @
d00dc3b0
...
...
@@ -151,8 +151,7 @@ public class GenUtils
{
int
lastIndex
=
packageName
.
lastIndexOf
(
"."
);
int
nameLength
=
packageName
.
length
();
String
moduleName
=
StringUtils
.
substring
(
packageName
,
lastIndex
+
1
,
nameLength
);
return
moduleName
;
return
StringUtils
.
substring
(
packageName
,
lastIndex
+
1
,
nameLength
);
}
/**
...
...
@@ -165,8 +164,7 @@ public class GenUtils
{
int
lastIndex
=
tableName
.
lastIndexOf
(
"_"
);
int
nameLength
=
tableName
.
length
();
String
businessName
=
StringUtils
.
substring
(
tableName
,
lastIndex
+
1
,
nameLength
);
return
businessName
;
return
StringUtils
.
substring
(
tableName
,
lastIndex
+
1
,
nameLength
);
}
/**
...
...
ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityUtils.java
View file @
d00dc3b0
...
...
@@ -228,8 +228,7 @@ public class VelocityUtils
public
static
String
getPackagePrefix
(
String
packageName
)
{
int
lastIndex
=
packageName
.
lastIndexOf
(
"."
);
String
basePackage
=
StringUtils
.
substring
(
packageName
,
0
,
lastIndex
);
return
basePackage
;
return
StringUtils
.
substring
(
packageName
,
0
,
lastIndex
);
}
/**
...
...
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDeptServiceImpl.java
View file @
d00dc3b0
...
...
@@ -63,12 +63,9 @@ public class SysDeptServiceImpl implements ISysDeptService
{
tempList
.
add
(
dept
.
getDeptId
());
}
for
(
Iterator
<
SysDept
>
iterator
=
depts
.
iterator
();
iterator
.
hasNext
();)
{
SysDept
dept
=
(
SysDept
)
iterator
.
next
();
for
(
SysDept
dept
:
depts
)
{
// 如果是顶级节点, 遍历该父节点的所有子节点
if
(!
tempList
.
contains
(
dept
.
getParentId
()))
{
if
(!
tempList
.
contains
(
dept
.
getParentId
()))
{
recursionFn
(
depts
,
dept
);
returnList
.
add
(
dept
);
}
...
...
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java
View file @
d00dc3b0
...
...
@@ -498,7 +498,7 @@ public class SysMenuServiceImpl implements ISysMenuService
*/
private
boolean
hasChild
(
List
<
SysMenu
>
list
,
SysMenu
t
)
{
return
getChildList
(
list
,
t
).
size
()
>
0
?
true
:
false
;
return
getChildList
(
list
,
t
).
size
()
>
0
;
}
/**
...
...
ruoyi-ui/src/utils/generator/drawingDefa
lu
t.js
→
ruoyi-ui/src/utils/generator/drawingDefa
ul
t.js
View file @
d00dc3b0
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 @
d00dc3b0
/* 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 @
d00dc3b0
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 @
d00dc3b0
<
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 @
d00dc3b0
<
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 @
d00dc3b0
<
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