Commit e92e7d49 authored by 赵啸非's avatar 赵啸非

修改前后端结构

parent 5ae1d98f
/* Logo 字体 */
@font-face {
font-family: "iconfont logo";
src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834');
src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834#iefix') format('embedded-opentype'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.woff?t=1545807318834') format('woff'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.ttf?t=1545807318834') format('truetype'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.svg?t=1545807318834#iconfont') format('svg');
}
.logo {
font-family: "iconfont logo";
font-size: 160px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
/* tabs */
.nav-tabs {
position: relative;
}
.nav-tabs .nav-more {
position: absolute;
right: 0;
bottom: 0;
height: 42px;
line-height: 42px;
color: #666;
}
#tabs {
border-bottom: 1px solid #eee;
}
#tabs li {
cursor: pointer;
width: 100px;
height: 40px;
line-height: 40px;
text-align: center;
font-size: 16px;
border-bottom: 2px solid transparent;
position: relative;
z-index: 1;
margin-bottom: -1px;
color: #666;
}
#tabs .active {
border-bottom-color: #f00;
color: #222;
}
.tab-container .content {
display: none;
}
/* 页面布局 */
.main {
padding: 30px 100px;
width: 960px;
margin: 0 auto;
}
.main .logo {
color: #333;
text-align: left;
margin-bottom: 30px;
line-height: 1;
height: 110px;
margin-top: -50px;
overflow: hidden;
*zoom: 1;
}
.main .logo a {
font-size: 160px;
color: #333;
}
.helps {
margin-top: 40px;
}
.helps pre {
padding: 20px;
margin: 10px 0;
border: solid 1px #e7e1cd;
background-color: #fffdef;
overflow: auto;
}
.icon_lists {
width: 100% !important;
overflow: hidden;
*zoom: 1;
}
.icon_lists li {
width: 100px;
margin-bottom: 10px;
margin-right: 20px;
text-align: center;
list-style: none !important;
cursor: default;
}
.icon_lists li .code-name {
line-height: 1.2;
}
.icon_lists .icon {
display: block;
height: 100px;
line-height: 100px;
font-size: 42px;
margin: 10px auto;
color: #333;
-webkit-transition: font-size 0.25s linear, width 0.25s linear;
-moz-transition: font-size 0.25s linear, width 0.25s linear;
transition: font-size 0.25s linear, width 0.25s linear;
}
.icon_lists .icon:hover {
font-size: 100px;
}
.icon_lists .svg-icon {
/* 通过设置 font-size 来改变图标大小 */
width: 1em;
/* 图标和文字相邻时,垂直对齐 */
vertical-align: -0.15em;
/* 通过设置 color 来改变 SVG 的颜色/fill */
fill: currentColor;
/* path 和 stroke 溢出 viewBox 部分在 IE 下会显示
normalize.css 中也包含这行 */
overflow: hidden;
}
.icon_lists li .name,
.icon_lists li .code-name {
color: #666;
}
/* markdown 样式 */
.markdown {
color: #666;
font-size: 14px;
line-height: 1.8;
}
.highlight {
line-height: 1.5;
}
.markdown img {
vertical-align: middle;
max-width: 100%;
}
.markdown h1 {
color: #404040;
font-weight: 500;
line-height: 40px;
margin-bottom: 24px;
}
.markdown h2,
.markdown h3,
.markdown h4,
.markdown h5,
.markdown h6 {
color: #404040;
margin: 1.6em 0 0.6em 0;
font-weight: 500;
clear: both;
}
.markdown h1 {
font-size: 28px;
}
.markdown h2 {
font-size: 22px;
}
.markdown h3 {
font-size: 16px;
}
.markdown h4 {
font-size: 14px;
}
.markdown h5 {
font-size: 12px;
}
.markdown h6 {
font-size: 12px;
}
.markdown hr {
height: 1px;
border: 0;
background: #e9e9e9;
margin: 16px 0;
clear: both;
}
.markdown p {
margin: 1em 0;
}
.markdown>p,
.markdown>blockquote,
.markdown>.highlight,
.markdown>ol,
.markdown>ul {
width: 80%;
}
.markdown ul>li {
list-style: circle;
}
.markdown>ul li,
.markdown blockquote ul>li {
margin-left: 20px;
padding-left: 4px;
}
.markdown>ul li p,
.markdown>ol li p {
margin: 0.6em 0;
}
.markdown ol>li {
list-style: decimal;
}
.markdown>ol li,
.markdown blockquote ol>li {
margin-left: 20px;
padding-left: 4px;
}
.markdown code {
margin: 0 3px;
padding: 0 5px;
background: #eee;
border-radius: 3px;
}
.markdown strong,
.markdown b {
font-weight: 600;
}
.markdown>table {
border-collapse: collapse;
border-spacing: 0px;
empty-cells: show;
border: 1px solid #e9e9e9;
width: 95%;
margin-bottom: 24px;
}
.markdown>table th {
white-space: nowrap;
color: #333;
font-weight: 600;
}
.markdown>table th,
.markdown>table td {
border: 1px solid #e9e9e9;
padding: 8px 16px;
text-align: left;
}
.markdown>table th {
background: #F7F7F7;
}
.markdown blockquote {
font-size: 90%;
color: #999;
border-left: 4px solid #e9e9e9;
padding-left: 0.8em;
margin: 1em 0;
}
.markdown blockquote p {
margin: 0;
}
.markdown .anchor {
opacity: 0;
transition: opacity 0.3s ease;
margin-left: 8px;
}
.markdown .waiting {
color: #ccc;
}
.markdown h1:hover .anchor,
.markdown h2:hover .anchor,
.markdown h3:hover .anchor,
.markdown h4:hover .anchor,
.markdown h5:hover .anchor,
.markdown h6:hover .anchor {
opacity: 1;
display: inline-block;
}
.markdown>br,
.markdown>p>br {
clear: both;
}
.hljs {
display: block;
background: white;
padding: 0.5em;
color: #333333;
overflow-x: auto;
}
.hljs-comment,
.hljs-meta {
color: #969896;
}
.hljs-string,
.hljs-variable,
.hljs-template-variable,
.hljs-strong,
.hljs-emphasis,
.hljs-quote {
color: #df5000;
}
.hljs-keyword,
.hljs-selector-tag,
.hljs-type {
color: #a71d5d;
}
.hljs-literal,
.hljs-symbol,
.hljs-bullet,
.hljs-attribute {
color: #0086b3;
}
.hljs-section,
.hljs-name {
color: #63a35c;
}
.hljs-tag {
color: #333333;
}
.hljs-title,
.hljs-attr,
.hljs-selector-id,
.hljs-selector-class,
.hljs-selector-attr,
.hljs-selector-pseudo {
color: #795da3;
}
.hljs-addition {
color: #55a532;
background-color: #eaffea;
}
.hljs-deletion {
color: #bd2c00;
background-color: #ffecec;
}
.hljs-link {
text-decoration: underline;
}
/* 代码高亮 */
/* PrismJS 1.15.0
https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript */
/**
* prism.js default theme for JavaScript, CSS and HTML
* Based on dabblet (http://dabblet.com)
* @author Lea Verou
*/
code[class*="language-"],
pre[class*="language-"] {
color: black;
background: none;
text-shadow: 0 1px white;
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
text-align: left;
white-space: pre;
word-spacing: normal;
word-break: normal;
word-wrap: normal;
line-height: 1.5;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
-webkit-hyphens: none;
-moz-hyphens: none;
-ms-hyphens: none;
hyphens: none;
}
pre[class*="language-"]::-moz-selection,
pre[class*="language-"] ::-moz-selection,
code[class*="language-"]::-moz-selection,
code[class*="language-"] ::-moz-selection {
text-shadow: none;
background: #b3d4fc;
}
pre[class*="language-"]::selection,
pre[class*="language-"] ::selection,
code[class*="language-"]::selection,
code[class*="language-"] ::selection {
text-shadow: none;
background: #b3d4fc;
}
@media print {
code[class*="language-"],
pre[class*="language-"] {
text-shadow: none;
}
}
/* Code blocks */
pre[class*="language-"] {
padding: 1em;
margin: .5em 0;
overflow: auto;
}
:not(pre)>code[class*="language-"],
pre[class*="language-"] {
background: #f5f2f0;
}
/* Inline code */
:not(pre)>code[class*="language-"] {
padding: .1em;
border-radius: .3em;
white-space: normal;
}
.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
color: slategray;
}
.token.punctuation {
color: #999;
}
.namespace {
opacity: .7;
}
.token.property,
.token.tag,
.token.boolean,
.token.number,
.token.constant,
.token.symbol,
.token.deleted {
color: #905;
}
.token.selector,
.token.attr-name,
.token.string,
.token.char,
.token.builtin,
.token.inserted {
color: #690;
}
.token.operator,
.token.entity,
.token.url,
.language-css .token.string,
.style .token.string {
color: #9a6e3a;
background: hsla(0, 0%, 100%, .5);
}
.token.atrule,
.token.attr-value,
.token.keyword {
color: #07a;
}
.token.function,
.token.class-name {
color: #DD4A68;
}
.token.regex,
.token.important,
.token.variable {
color: #e90;
}
.token.important,
.token.bold {
font-weight: bold;
}
.token.italic {
font-style: italic;
}
.token.entity {
cursor: help;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>iconfont Demo</title>
<link rel="shortcut icon" href="//img.alicdn.com/imgextra/i4/O1CN01Z5paLz1O0zuCC7osS_!!6000000001644-55-tps-83-82.svg" type="image/x-icon"/>
<link rel="icon" type="image/svg+xml" href="//img.alicdn.com/imgextra/i4/O1CN01Z5paLz1O0zuCC7osS_!!6000000001644-55-tps-83-82.svg"/>
<link rel="stylesheet" href="https://g.alicdn.com/thx/cube/1.3.2/cube.min.css">
<link rel="stylesheet" href="demo.css">
<link rel="stylesheet" href="iconfont.css">
<script src="iconfont.js"></script>
<!-- jQuery -->
<script src="https://a1.alicdn.com/oss/uploads/2018/12/26/7bfddb60-08e8-11e9-9b04-53e73bb6408b.js"></script>
<!-- 代码高亮 -->
<script src="https://a1.alicdn.com/oss/uploads/2018/12/26/a3f714d0-08e6-11e9-8a15-ebf944d7534c.js"></script>
<style>
.main .logo {
margin-top: 0;
height: auto;
}
.main .logo a {
display: flex;
align-items: center;
}
.main .logo .sub-title {
margin-left: 0.5em;
font-size: 22px;
color: #fff;
background: linear-gradient(-45deg, #3967FF, #B500FE);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
</style>
</head>
<body>
<div class="main">
<h1 class="logo"><a href="https://www.iconfont.cn/" title="iconfont 首页" target="_blank">
<img width="200" src="https://img.alicdn.com/imgextra/i3/O1CN01Mn65HV1FfSEzR6DKv_!!6000000000514-55-tps-228-59.svg">
</a></h1>
<div class="nav-tabs">
<ul id="tabs" class="dib-box">
<li class="dib active"><span>Unicode</span></li>
<li class="dib"><span>Font class</span></li>
<li class="dib"><span>Symbol</span></li>
</ul>
<a href="https://www.iconfont.cn/manage/index?manage_type=myprojects&projectId=3597207" target="_blank" class="nav-more">查看项目</a>
</div>
<div class="tab-container">
<div class="content unicode" style="display: block;">
<ul class="icon_lists dib-box">
<li class="dib">
<span class="icon iconfont">&#xe627;</span>
<div class="name">系统管理-部门管理</div>
<div class="code-name">&amp;#xe627;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe751;</span>
<div class="name">首页</div>
<div class="code-name">&amp;#xe751;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe64b;</span>
<div class="name">设置</div>
<div class="code-name">&amp;#xe64b;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe60d;</span>
<div class="name">消息</div>
<div class="code-name">&amp;#xe60d;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xec34;</span>
<div class="name">告警</div>
<div class="code-name">&amp;#xec34;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe6bc;</span>
<div class="name">大楼</div>
<div class="code-name">&amp;#xe6bc;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe632;</span>
<div class="name">系统管理</div>
<div class="code-name">&amp;#xe632;</div>
</li>
</ul>
<div class="article markdown">
<h2 id="unicode-">Unicode 引用</h2>
<hr>
<p>Unicode 是字体在网页端最原始的应用方式,特点是:</p>
<ul>
<li>支持按字体的方式去动态调整图标大小,颜色等等。</li>
<li>默认情况下不支持多色,直接添加多色图标会自动去色。</li>
</ul>
<blockquote>
<p>注意:新版 iconfont 支持两种方式引用多色图标:SVG symbol 引用方式和彩色字体图标模式。(使用彩色字体图标需要在「编辑项目」中开启「彩色」选项后并重新生成。)</p>
</blockquote>
<p>Unicode 使用步骤如下:</p>
<h3 id="-font-face">第一步:拷贝项目下面生成的 <code>@font-face</code></h3>
<pre><code class="language-css"
>@font-face {
font-family: 'iconfont';
src: url('iconfont.woff2?t=1660811949301') format('woff2'),
url('iconfont.woff?t=1660811949301') format('woff'),
url('iconfont.ttf?t=1660811949301') format('truetype');
}
</code></pre>
<h3 id="-iconfont-">第二步:定义使用 iconfont 的样式</h3>
<pre><code class="language-css"
>.iconfont {
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
</code></pre>
<h3 id="-">第三步:挑选相应图标并获取字体编码,应用于页面</h3>
<pre>
<code class="language-html"
>&lt;span class="iconfont"&gt;&amp;#x33;&lt;/span&gt;
</code></pre>
<blockquote>
<p>"iconfont" 是你项目下的 font-family。可以通过编辑项目查看,默认是 "iconfont"。</p>
</blockquote>
</div>
</div>
<div class="content font-class">
<ul class="icon_lists dib-box">
<li class="dib">
<span class="icon iconfont icon-xitongguanli"></span>
<div class="name">
系统管理-部门管理
</div>
<div class="code-name">.icon-xitongguanli
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-shouye"></span>
<div class="name">
首页
</div>
<div class="code-name">.icon-shouye
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-shezhi"></span>
<div class="name">
设置
</div>
<div class="code-name">.icon-shezhi
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-xiaoxi"></span>
<div class="name">
消息
</div>
<div class="code-name">.icon-xiaoxi
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-gaojing"></span>
<div class="name">
告警
</div>
<div class="code-name">.icon-gaojing
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-dalou"></span>
<div class="name">
大楼
</div>
<div class="code-name">.icon-dalou
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-xitongguanli1"></span>
<div class="name">
系统管理
</div>
<div class="code-name">.icon-xitongguanli1
</div>
</li>
</ul>
<div class="article markdown">
<h2 id="font-class-">font-class 引用</h2>
<hr>
<p>font-class 是 Unicode 使用方式的一种变种,主要是解决 Unicode 书写不直观,语意不明确的问题。</p>
<p>与 Unicode 使用方式相比,具有如下特点:</p>
<ul>
<li>相比于 Unicode 语意明确,书写更直观。可以很容易分辨这个 icon 是什么。</li>
<li>因为使用 class 来定义图标,所以当要替换图标时,只需要修改 class 里面的 Unicode 引用。</li>
</ul>
<p>使用步骤如下:</p>
<h3 id="-fontclass-">第一步:引入项目下面生成的 fontclass 代码:</h3>
<pre><code class="language-html">&lt;link rel="stylesheet" href="./iconfont.css"&gt;
</code></pre>
<h3 id="-">第二步:挑选相应图标并获取类名,应用于页面:</h3>
<pre><code class="language-html">&lt;span class="iconfont icon-xxx"&gt;&lt;/span&gt;
</code></pre>
<blockquote>
<p>"
iconfont" 是你项目下的 font-family。可以通过编辑项目查看,默认是 "iconfont"。</p>
</blockquote>
</div>
</div>
<div class="content symbol">
<ul class="icon_lists dib-box">
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-xitongguanli"></use>
</svg>
<div class="name">系统管理-部门管理</div>
<div class="code-name">#icon-xitongguanli</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-shouye"></use>
</svg>
<div class="name">首页</div>
<div class="code-name">#icon-shouye</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-shezhi"></use>
</svg>
<div class="name">设置</div>
<div class="code-name">#icon-shezhi</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-xiaoxi"></use>
</svg>
<div class="name">消息</div>
<div class="code-name">#icon-xiaoxi</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-gaojing"></use>
</svg>
<div class="name">告警</div>
<div class="code-name">#icon-gaojing</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-dalou"></use>
</svg>
<div class="name">大楼</div>
<div class="code-name">#icon-dalou</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-xitongguanli1"></use>
</svg>
<div class="name">系统管理</div>
<div class="code-name">#icon-xitongguanli1</div>
</li>
</ul>
<div class="article markdown">
<h2 id="symbol-">Symbol 引用</h2>
<hr>
<p>这是一种全新的使用方式,应该说这才是未来的主流,也是平台目前推荐的用法。相关介绍可以参考这篇<a href="">文章</a>
这种用法其实是做了一个 SVG 的集合,与另外两种相比具有如下特点:</p>
<ul>
<li>支持多色图标了,不再受单色限制。</li>
<li>通过一些技巧,支持像字体那样,通过 <code>font-size</code>, <code>color</code> 来调整样式。</li>
<li>兼容性较差,支持 IE9+,及现代浏览器。</li>
<li>浏览器渲染 SVG 的性能一般,还不如 png。</li>
</ul>
<p>使用步骤如下:</p>
<h3 id="-symbol-">第一步:引入项目下面生成的 symbol 代码:</h3>
<pre><code class="language-html">&lt;script src="./iconfont.js"&gt;&lt;/script&gt;
</code></pre>
<h3 id="-css-">第二步:加入通用 CSS 代码(引入一次就行):</h3>
<pre><code class="language-html">&lt;style&gt;
.icon {
width: 1em;
height: 1em;
vertical-align: -0.15em;
fill: currentColor;
overflow: hidden;
}
&lt;/style&gt;
</code></pre>
<h3 id="-">第三步:挑选相应图标并获取类名,应用于页面:</h3>
<pre><code class="language-html">&lt;svg class="icon" aria-hidden="true"&gt;
&lt;use xlink:href="#icon-xxx"&gt;&lt;/use&gt;
&lt;/svg&gt;
</code></pre>
</div>
</div>
</div>
</div>
<script>
$(document).ready(function () {
$('.tab-container .content:first').show()
$('#tabs li').click(function (e) {
var tabContent = $('.tab-container .content')
var index = $(this).index()
if ($(this).hasClass('active')) {
return
} else {
$('#tabs li').removeClass('active')
$(this).addClass('active')
tabContent.hide().eq(index).fadeIn()
}
})
})
</script>
</body>
</html>
@font-face {
font-family: "iconfont"; /* Project id 3597207 */
src: url('iconfont.woff2?t=1660811949301') format('woff2'),
url('iconfont.woff?t=1660811949301') format('woff'),
url('iconfont.ttf?t=1660811949301') format('truetype');
}
.iconfont {
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-xitongguanli:before {
content: "\e627";
}
.icon-shouye:before {
content: "\e751";
}
.icon-shezhi:before {
content: "\e64b";
}
.icon-xiaoxi:before {
content: "\e60d";
}
.icon-gaojing:before {
content: "\ec34";
}
.icon-dalou:before {
content: "\e6bc";
}
.icon-xitongguanli1:before {
content: "\e632";
}
!function(a){var t,l,e,c,o,n='<svg><symbol id="icon-xitongguanli" viewBox="0 0 1024 1024"><path d="M894.7 597.8h-94.1v-65.9c-0.3-16.4-13.9-29.5-30.4-29.2H542.1V454c83.7-16.7 138.1-98.2 121.3-181.9-16.7-83.7-98.2-138.1-181.9-121.3-83.7 16.7-138.1 98.2-121.3 181.9 12.2 61.2 60.1 109.1 121.3 121.3v48.6H253.3c-16.4-0.3-30 12.8-30.4 29.2v65.9h-94.1c-16.4-0.2-29.9 12.8-30.2 29.2v240c0.3 16.4 13.8 29.4 30.2 29.2h248.7c16.4 0.3 29.9-12.7 30.2-29.1V627c-0.3-16.4-13.7-29.4-30.1-29.2H283.4V561h456.7v36.8H646c-16.4-0.3-29.9 12.7-30.2 29.1V867c0.3 16.4 13.7 29.4 30.1 29.2H894.7c16.4 0.2 29.9-12.8 30.2-29.2V627c-0.3-16.4-13.8-29.5-30.2-29.2z m-547.4 58.3v181.7H159V656.1h188.3z m70.3-348.4c-1.9-52 38.8-95.7 90.8-97.5 52-1.9 95.7 38.8 97.5 90.8 1.9 52-38.8 95.7-90.8 97.5-1.2 0-2.3 0.1-3.5 0.1-50.9 0.7-93-39.9-94-90.9z m446.9 530.1H676.2V656.1h188.3v181.7z" fill="#333333" ></path></symbol><symbol id="icon-shouye" viewBox="0 0 1024 1024"><path d="M979.792374 404.577188 574.183101 83.942886c-34.918864-27.694272-89.619352-27.694272-124.538216 0L44.207626 404.577188c-13.933143 11.008903-16.169326 31.134554-5.332437 44.895683s30.618512 16.169326 44.551655 5.332437l12.55703-10.320847 0 387.547791c0 54.872501 57.968755 95.983874 108.712918 95.983874l639.892491 0c50.22812 0 83.254829-38.531161 83.254829-95.983874L927.844112 445.860575l11.69696 8.944734c5.84848 4.644381 13.073072 6.880564 20.125651 6.880564 9.460776 0 18.921552-4.128339 25.286074-12.213002C995.9617 435.711742 993.725517 415.586091 979.792374 404.577188zM479.919368 864.026877 479.919368 686.508315c0-8.77272 15.997312-13.245087 31.994625-13.245087s31.994625 4.472367 31.994625 13.245087l0 177.346548L479.919368 864.026877 479.919368 864.026877zM864.026877 832.032253c0 21.157736-5.84848 31.994625-19.26558 31.994625L608.585923 864.026877c0-0.516042-0.688056-0.860071-0.688056-1.376113L607.897867 686.508315c0-37.155048-29.930455-77.234336-95.983874-77.234336s-95.983874 40.079288-95.983874 77.234336l0 176.142449c0 0.516042 0.860071 0.860071 0.860071 1.376113L204.868806 864.026877c-20.125651 0-44.723669-17.373425-44.723669-31.994625L160.145137 393.740299 488.864102 134.171006c11.868974-9.288762 33.198723-9.288762 44.895683 0l330.095078 261.11742L863.854863 832.032253z" ></path></symbol><symbol id="icon-shezhi" viewBox="0 0 1024 1024"><path d="M512 697.6c102.4 0 182.4-83.2 182.4-185.6 0-102.4-83.2-185.6-182.4-185.6-102.4 0-182.4 83.2-182.4 185.6C329.6 614.4 412.8 697.6 512 697.6L512 697.6zM512 646.4c-73.6 0-134.4-60.8-134.4-134.4 0-73.6 60.8-134.4 134.4-134.4 73.6 0 134.4 60.8 134.4 134.4C646.4 585.6 585.6 646.4 512 646.4L512 646.4z" ></path><path d="M249.015232 843.178592c35.2 28.8 73.6 51.2 112 67.2 41.6-38.4 96-60.8 150.4-60.8 57.6 0 108.8 22.4 150.4 60.8 41.6-16 80-38.4 112-67.2-12.8-54.4-3.2-112 22.4-163.2 28.8-48 73.6-86.4 128-102.4 3.2-22.4 6.4-44.8 6.4-67.2 0-22.4-3.2-44.8-6.4-67.2-54.4-16-99.2-54.4-128-102.4-28.8-48-35.2-108.8-22.4-163.2-35.2-28.8-73.6-51.2-112-67.2-41.6 38.4-92.8 60.8-150.4 60.8-54.4 0-108.8-22.4-150.4-60.8-41.6 16-80 38.4-112 67.2 12.8 54.4 3.2 112-22.4 163.2-28.8 48-73.6 86.4-128 102.4-3.2 22.4-6.4 44.8-6.4 67.2 0 22.4 3.2 44.8 6.4 67.2 54.4 16 99.2 54.4 128 102.4C252.215232 731.178592 261.815232 788.778592 249.015232 843.178592M361.015232 958.378592c-54.4-19.2-105.6-48-150.4-89.6-6.4-6.4-9.6-16-6.4-22.4 16-48 9.6-99.2-16-140.8-25.6-44.8-64-73.6-112-83.2-9.6-3.2-16-9.6-16-19.2-6.4-28.8-9.6-60.8-9.6-89.6 0-28.8 3.2-57.6 9.6-89.6 3.2-9.6 9.6-16 16-19.2 48-12.8 89.6-41.6 112-83.2 25.6-44.8 28.8-92.8 16-140.8-3.2-9.6 0-19.2 6.4-22.4 44.8-38.4 96-67.2 150.4-89.6 9.6-3.2 16 0 22.4 6.4 35.2 35.2 80 57.6 128 57.6 48 0 96-19.2 128-57.6 6.4-6.4 16-9.6 22.4-6.4 54.4 19.2 105.6 48 150.4 89.6 6.4 6.4 9.6 16 6.4 22.4-16 48-9.6 99.2 16 140.8 25.6 44.8 64 73.6 112 83.2 9.6 3.2 16 9.6 16 19.2 6.4 28.8 9.6 60.8 9.6 89.6 0 28.8-3.2 57.6-9.6 89.6-3.2 9.6-9.6 16-16 19.2-48 12.8-89.6 41.6-112 83.2-25.6 44.8-28.8 92.8-16 140.8 3.2 9.6 0 19.2-6.4 22.4-44.8 38.4-96 67.2-150.4 89.6-9.6 3.2-16 0-22.4-6.4-35.2-35.2-80-57.6-128-57.6-48 0-96 19.2-128 57.6-3.2 3.2-9.6 6.4-16 6.4C364.215232 958.378592 361.015232 958.378592 361.015232 958.378592z" ></path></symbol><symbol id="icon-xiaoxi" viewBox="0 0 1024 1024"><path d="M901.89824 125.31712H122.88c-67.75808 0-122.88 55.12192-122.88 122.88v552.97024c0 67.75808 55.12192 122.88 122.88 122.88h779.01824c67.75808 0 122.88-55.12192 122.88-122.88V248.19712c0-67.74784-55.12192-122.88-122.88-122.88z m81.92 675.85024c0 45.16864-36.75136 81.92-81.92 81.92H122.88c-45.16864 0-81.92-36.75136-81.92-81.92V248.19712c0-45.16864 36.75136-81.92 81.92-81.92h779.01824c45.16864 0 81.92 36.75136 81.92 81.92v552.97024z" fill="" ></path><path d="M527.7184 502.43584a21.7088 21.7088 0 0 1-30.65856 0L206.00832 211.39456l-28.95872 28.95872 291.05152 291.05152c12.21632 12.20608 28.25216 18.31936 44.288 18.31936s32.08192-6.11328 44.288-18.31936l291.05152-291.05152-28.95872-28.95872-291.05152 291.04128z" fill="" ></path></symbol><symbol id="icon-gaojing" viewBox="0 0 1024 1024"><path d="M192 832a32 32 0 0 0 0 64h640a32 32 0 0 0 0-64H192z m0-64h640a96 96 0 0 1 0 192H192a96 96 0 0 1 0-192z" ></path><path d="M816 208m-48 0a48 48 0 1 0 96 0 48 48 0 1 0-96 0Z" ></path><path d="M208 208m-48 0a48 48 0 1 0 96 0 48 48 0 1 0-96 0Z" ></path><path d="M480 608a32 32 0 0 1 64 0v160a32 32 0 0 1-64 0v-160z" ></path><path d="M512 640a112 112 0 1 1 0-224 112 112 0 0 1 0 224z m0-64a48 48 0 1 0 0-96 48 48 0 0 0 0 96zM864 480a32 32 0 0 1 0-64h96a32 32 0 0 1 0 64h-96zM64 480a32 32 0 0 1 0-64h96a32 32 0 0 1 0 64H64zM480 64a32 32 0 0 1 64 0v96a32 32 0 0 1-64 0V64z" ></path><path d="M272.448 800h-64v-288a304 304 0 0 1 608 0v288h-64v-288a240 240 0 0 0-480 0v288z" ></path></symbol><symbol id="icon-dalou" viewBox="0 0 1024 1024"><path d="M981.333333 1024h-938.666666a42.666667 42.666667 0 0 1 0-85.333333H85.333333V128A128 128 0 0 1 213.333333 0h302.506667a128 128 0 0 1 128 128v224l202.24 58.453333A128 128 0 0 1 938.666667 533.333333V938.666667h42.666666a42.666667 42.666667 0 0 1 0 85.333333z m-337.493333-85.333333H853.333333V533.333333a42.666667 42.666667 0 0 0-30.72-42.666666l-178.773333-51.626667v148.906667h85.333333a42.666667 42.666667 0 0 1 0 85.333333h-85.333333v72.106667h85.333333a42.666667 42.666667 0 0 1 0 85.333333h-85.333333V938.666667z m-151.04 0h65.706667V128a42.666667 42.666667 0 0 0-42.666667-42.666667H213.333333A42.666667 42.666667 0 0 0 170.666667 128V938.666667h66.133333v-170.666667a42.666667 42.666667 0 0 1 42.666667-42.666667h170.666666a42.666667 42.666667 0 0 1 42.666667 42.666667v170.666667z m-170.666667 0h85.333334v-128h-85.333334V938.666667z m128-320h-170.666666a42.666667 42.666667 0 0 1 0-85.333334h170.666666a42.666667 42.666667 0 0 1 0 85.333334z m0-170.666667h-170.666666a42.666667 42.666667 0 0 1 0-85.333333h170.666666a42.666667 42.666667 0 0 1 0 85.333333z m0-170.666667h-170.666666a42.666667 42.666667 0 0 1 0-85.333333h170.666666a42.666667 42.666667 0 0 1 0 85.333333z" ></path></symbol><symbol id="icon-xitongguanli1" viewBox="0 0 1024 1024"><path d="M446.805333 955.716267a381.405867 381.405867 0 0 0 133.597867 66.730666c2.7136 0.733867 13.346133 1.2288 29.0816 1.536h-404.650667a34.1504 34.1504 0 0 1 0-68.266666H446.805333z m318.293334-570.043734l3.1232 0.699734a308.002133 308.002133 0 0 1 123.2896 66.884266l6.109866 5.597867a33.109333 33.109333 0 0 1 10.3424 27.818667l-6.417066 57.275733a8.0384 8.0384 0 0 0 4.949333 8.2944l54.442667 23.261867a34.133333 34.133333 0 0 1 18.858666 19.899733l0.8192 2.696533a287.914667 287.914667 0 0 1 1.9456 136.789334l-1.9456 7.936c-2.6112 10.069333-9.8816 18.432-19.694933 22.613333l-54.442667 23.261867a8.0384 8.0384 0 0 0-4.932266 8.2944l6.417066 57.224533a33.024 33.024 0 0 1-8.328533 25.770667l-1.9968 2.048a307.319467 307.319467 0 0 1-121.344 70.126933l-8.072533 2.338133c-2.048 0.546133-4.1472 0.9216-6.263467 1.092267l-3.191467 0.136533c-7.389867 0-14.592-2.286933-20.565333-6.5024l-48.008533-34.065066a8.567467 8.567467 0 0 0-9.8816 0l-48.008534 34.065066a35.669333 35.669333 0 0 1-26.914133 5.9392l-3.106133-0.7168a308.0192 308.0192 0 0 1-123.2896-66.8672l-6.144-5.614933a33.109333 33.109333 0 0 1-10.325334-27.8016l6.434134-57.224533a8.055467 8.055467 0 0 0-4.949334-8.2944l-54.442666-23.261867a34.133333 34.133333 0 0 1-18.858667-19.899733l-0.836267-2.7136a287.914667 287.914667 0 0 1-1.928533-136.789334l1.928533-7.936c2.628267-10.069333 9.898667-18.397867 19.712-22.596266l54.408534-23.261867a8.055467 8.055467 0 0 0 4.949333-8.2944l-6.417067-57.224533a33.024 33.024 0 0 1 8.328534-25.770667l1.9968-2.048a307.3536 307.3536 0 0 1 121.344-70.144l8.072533-2.338133a35.703467 35.703467 0 0 1 30.020267 5.256533l48.008533 34.048a8.567467 8.567467 0 0 0 9.898667 0l48.008533-34.048a35.618133 35.618133 0 0 1 23.773867-6.382933l3.1232 0.426666zM853.333333 0C947.5072 0 1024 71.406933 1024 159.232v400.503467a5.205333 5.205333 0 0 0-0.989867-1.604267l-0.546133-0.392533-66.747733-28.3648v-67.6864l1.467733-12.868267a39.901867 39.901867 0 0 0-1.4336-15.940267l-0.034133-273.629866C955.733333 109.090133 909.824 68.266667 853.333333 68.266667H170.666667c-56.507733 0-102.4 40.789333-102.4 90.965333v568.9344c0 50.158933 45.892267 90.965333 102.4 90.965333h239.36c3.566933 1.536 5.888 4.864 6.075733 8.533334l-0.0512 1.604266-6.570667 58.129067H170.683733C76.6464 887.432533 0 816.042667 0 728.200533V159.249067C0 71.406933 76.629333 0 170.683733 0H853.333333z m-88.302933 456.174933l-33.706667 23.893334a79.701333 79.701333 0 0 1-92.1088 0l-33.723733-23.893334a237.789867 237.789867 0 0 0-71.850667 40.277334l4.522667 40.157866c3.771733 32.750933-14.8992 64.068267-46.062933 77.294934l-38.1952 16.315733a222.993067 222.993067 0 0 0 0 80.384l38.1952 16.3328c31.163733 13.226667 49.834667 44.544 46.08 77.294933l-4.5568 40.174934a237.7216 237.7216 0 0 0 71.850666 40.277333l33.706667-23.927467a79.394133 79.394133 0 0 1 41.5744-14.523733l4.5056-0.119467a79.530667 79.530667 0 0 1 46.08 14.6432l33.6896 23.893334a237.602133 237.602133 0 0 0 71.850667-40.260267l-4.5056-40.174933c-3.754667-32.750933 14.8992-64.068267 46.045866-77.277867l38.212267-16.2816a222.993067 222.993067 0 0 0 0-80.401067l-38.212267-16.349866c-31.146667-13.226667-49.8176-44.544-46.045866-77.312l4.5056-40.1408a237.6192 237.6192 0 0 0-71.850667-40.277334z m-79.7696 75.605334c78.8992 0 143.069867 62.173867 143.069867 138.5984 0 76.4416-64.170667 138.615467-143.069867 138.615466-78.882133 0-143.0528-62.173867-143.0528-138.615466 0-76.424533 64.170667-138.5984 143.0528-138.5984z m0 67.413333c-40.567467 0-73.454933 31.880533-73.454933 71.185067 0 39.3216 32.887467 71.185067 73.454933 71.185066 39.355733 0 71.4752-29.969067 73.386667-67.618133l0.085333-3.549867c-0.0512-38.109867-30.941867-69.205333-69.802667-71.099733l-3.669333-0.085333z" fill="#121649" ></path></symbol></svg>',i=(i=document.getElementsByTagName("script"))[i.length-1].getAttribute("data-injectcss"),h=function(a,t){t.parentNode.insertBefore(a,t)};if(i&&!a.__iconfont__svg__cssinject__){a.__iconfont__svg__cssinject__=!0;try{document.write("<style>.svgfont {display: inline-block;width: 1em;height: 1em;fill: currentColor;vertical-align: -0.1em;font-size:16px;}</style>")}catch(a){console&&console.log(a)}}function d(){o||(o=!0,e())}function s(){try{c.documentElement.doScroll("left")}catch(a){return void setTimeout(s,50)}d()}t=function(){var a,t=document.createElement("div");t.innerHTML=n,n=null,(t=t.getElementsByTagName("svg")[0])&&(t.setAttribute("aria-hidden","true"),t.style.position="absolute",t.style.width=0,t.style.height=0,t.style.overflow="hidden",t=t,(a=document.body).firstChild?h(t,a.firstChild):a.appendChild(t))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(t,0):(l=function(){document.removeEventListener("DOMContentLoaded",l,!1),t()},document.addEventListener("DOMContentLoaded",l,!1)):document.attachEvent&&(e=t,c=a.document,o=!1,s(),c.onreadystatechange=function(){"complete"==c.readyState&&(c.onreadystatechange=null,d())})}(window);
\ No newline at end of file
{
"id": "3597207",
"name": "物联网",
"font_family": "iconfont",
"css_prefix_text": "icon-",
"description": "",
"glyphs": [
{
"icon_id": "12889883",
"name": "系统管理-部门管理",
"font_class": "xitongguanli",
"unicode": "e627",
"unicode_decimal": 58919
},
{
"icon_id": "577364",
"name": "首页",
"font_class": "shouye",
"unicode": "e751",
"unicode_decimal": 59217
},
{
"icon_id": "629333",
"name": "设置",
"font_class": "shezhi",
"unicode": "e64b",
"unicode_decimal": 58955
},
{
"icon_id": "1311632",
"name": "消息",
"font_class": "xiaoxi",
"unicode": "e60d",
"unicode_decimal": 58893
},
{
"icon_id": "5764445",
"name": "告警",
"font_class": "gaojing",
"unicode": "ec34",
"unicode_decimal": 60468
},
{
"icon_id": "8361756",
"name": "大楼",
"font_class": "dalou",
"unicode": "e6bc",
"unicode_decimal": 59068
},
{
"icon_id": "12820187",
"name": "系统管理",
"font_class": "xitongguanli1",
"unicode": "e632",
"unicode_decimal": 58930
}
]
}
/* Logo 字体 */
@font-face {
font-family: "iconfont logo";
src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834');
src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834#iefix') format('embedded-opentype'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.woff?t=1545807318834') format('woff'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.ttf?t=1545807318834') format('truetype'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.svg?t=1545807318834#iconfont') format('svg');
}
.logo {
font-family: "iconfont logo";
font-size: 160px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
/* tabs */
.nav-tabs {
position: relative;
}
.nav-tabs .nav-more {
position: absolute;
right: 0;
bottom: 0;
height: 42px;
line-height: 42px;
color: #666;
}
#tabs {
border-bottom: 1px solid #eee;
}
#tabs li {
cursor: pointer;
width: 100px;
height: 40px;
line-height: 40px;
text-align: center;
font-size: 16px;
border-bottom: 2px solid transparent;
position: relative;
z-index: 1;
margin-bottom: -1px;
color: #666;
}
#tabs .active {
border-bottom-color: #f00;
color: #222;
}
.tab-container .content {
display: none;
}
/* 页面布局 */
.main {
padding: 30px 100px;
width: 960px;
margin: 0 auto;
}
.main .logo {
color: #333;
text-align: left;
margin-bottom: 30px;
line-height: 1;
height: 110px;
margin-top: -50px;
overflow: hidden;
*zoom: 1;
}
.main .logo a {
font-size: 160px;
color: #333;
}
.helps {
margin-top: 40px;
}
.helps pre {
padding: 20px;
margin: 10px 0;
border: solid 1px #e7e1cd;
background-color: #fffdef;
overflow: auto;
}
.icon_lists {
width: 100% !important;
overflow: hidden;
*zoom: 1;
}
.icon_lists li {
width: 100px;
margin-bottom: 10px;
margin-right: 20px;
text-align: center;
list-style: none !important;
cursor: default;
}
.icon_lists li .code-name {
line-height: 1.2;
}
.icon_lists .icon {
display: block;
height: 100px;
line-height: 100px;
font-size: 42px;
margin: 10px auto;
color: #333;
-webkit-transition: font-size 0.25s linear, width 0.25s linear;
-moz-transition: font-size 0.25s linear, width 0.25s linear;
transition: font-size 0.25s linear, width 0.25s linear;
}
.icon_lists .icon:hover {
font-size: 100px;
}
.icon_lists .svg-icon {
/* 通过设置 font-size 来改变图标大小 */
width: 1em;
/* 图标和文字相邻时,垂直对齐 */
vertical-align: -0.15em;
/* 通过设置 color 来改变 SVG 的颜色/fill */
fill: currentColor;
/* path 和 stroke 溢出 viewBox 部分在 IE 下会显示
normalize.css 中也包含这行 */
overflow: hidden;
}
.icon_lists li .name,
.icon_lists li .code-name {
color: #666;
}
/* markdown 样式 */
.markdown {
color: #666;
font-size: 14px;
line-height: 1.8;
}
.highlight {
line-height: 1.5;
}
.markdown img {
vertical-align: middle;
max-width: 100%;
}
.markdown h1 {
color: #404040;
font-weight: 500;
line-height: 40px;
margin-bottom: 24px;
}
.markdown h2,
.markdown h3,
.markdown h4,
.markdown h5,
.markdown h6 {
color: #404040;
margin: 1.6em 0 0.6em 0;
font-weight: 500;
clear: both;
}
.markdown h1 {
font-size: 28px;
}
.markdown h2 {
font-size: 22px;
}
.markdown h3 {
font-size: 16px;
}
.markdown h4 {
font-size: 14px;
}
.markdown h5 {
font-size: 12px;
}
.markdown h6 {
font-size: 12px;
}
.markdown hr {
height: 1px;
border: 0;
background: #e9e9e9;
margin: 16px 0;
clear: both;
}
.markdown p {
margin: 1em 0;
}
.markdown>p,
.markdown>blockquote,
.markdown>.highlight,
.markdown>ol,
.markdown>ul {
width: 80%;
}
.markdown ul>li {
list-style: circle;
}
.markdown>ul li,
.markdown blockquote ul>li {
margin-left: 20px;
padding-left: 4px;
}
.markdown>ul li p,
.markdown>ol li p {
margin: 0.6em 0;
}
.markdown ol>li {
list-style: decimal;
}
.markdown>ol li,
.markdown blockquote ol>li {
margin-left: 20px;
padding-left: 4px;
}
.markdown code {
margin: 0 3px;
padding: 0 5px;
background: #eee;
border-radius: 3px;
}
.markdown strong,
.markdown b {
font-weight: 600;
}
.markdown>table {
border-collapse: collapse;
border-spacing: 0px;
empty-cells: show;
border: 1px solid #e9e9e9;
width: 95%;
margin-bottom: 24px;
}
.markdown>table th {
white-space: nowrap;
color: #333;
font-weight: 600;
}
.markdown>table th,
.markdown>table td {
border: 1px solid #e9e9e9;
padding: 8px 16px;
text-align: left;
}
.markdown>table th {
background: #F7F7F7;
}
.markdown blockquote {
font-size: 90%;
color: #999;
border-left: 4px solid #e9e9e9;
padding-left: 0.8em;
margin: 1em 0;
}
.markdown blockquote p {
margin: 0;
}
.markdown .anchor {
opacity: 0;
transition: opacity 0.3s ease;
margin-left: 8px;
}
.markdown .waiting {
color: #ccc;
}
.markdown h1:hover .anchor,
.markdown h2:hover .anchor,
.markdown h3:hover .anchor,
.markdown h4:hover .anchor,
.markdown h5:hover .anchor,
.markdown h6:hover .anchor {
opacity: 1;
display: inline-block;
}
.markdown>br,
.markdown>p>br {
clear: both;
}
.hljs {
display: block;
background: white;
padding: 0.5em;
color: #333333;
overflow-x: auto;
}
.hljs-comment,
.hljs-meta {
color: #969896;
}
.hljs-string,
.hljs-variable,
.hljs-template-variable,
.hljs-strong,
.hljs-emphasis,
.hljs-quote {
color: #df5000;
}
.hljs-keyword,
.hljs-selector-tag,
.hljs-type {
color: #a71d5d;
}
.hljs-literal,
.hljs-symbol,
.hljs-bullet,
.hljs-attribute {
color: #0086b3;
}
.hljs-section,
.hljs-name {
color: #63a35c;
}
.hljs-tag {
color: #333333;
}
.hljs-title,
.hljs-attr,
.hljs-selector-id,
.hljs-selector-class,
.hljs-selector-attr,
.hljs-selector-pseudo {
color: #795da3;
}
.hljs-addition {
color: #55a532;
background-color: #eaffea;
}
.hljs-deletion {
color: #bd2c00;
background-color: #ffecec;
}
.hljs-link {
text-decoration: underline;
}
/* 代码高亮 */
/* PrismJS 1.15.0
https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript */
/**
* prism.js default theme for JavaScript, CSS and HTML
* Based on dabblet (http://dabblet.com)
* @author Lea Verou
*/
code[class*="language-"],
pre[class*="language-"] {
color: black;
background: none;
text-shadow: 0 1px white;
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
text-align: left;
white-space: pre;
word-spacing: normal;
word-break: normal;
word-wrap: normal;
line-height: 1.5;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
-webkit-hyphens: none;
-moz-hyphens: none;
-ms-hyphens: none;
hyphens: none;
}
pre[class*="language-"]::-moz-selection,
pre[class*="language-"] ::-moz-selection,
code[class*="language-"]::-moz-selection,
code[class*="language-"] ::-moz-selection {
text-shadow: none;
background: #b3d4fc;
}
pre[class*="language-"]::selection,
pre[class*="language-"] ::selection,
code[class*="language-"]::selection,
code[class*="language-"] ::selection {
text-shadow: none;
background: #b3d4fc;
}
@media print {
code[class*="language-"],
pre[class*="language-"] {
text-shadow: none;
}
}
/* Code blocks */
pre[class*="language-"] {
padding: 1em;
margin: .5em 0;
overflow: auto;
}
:not(pre)>code[class*="language-"],
pre[class*="language-"] {
background: #f5f2f0;
}
/* Inline code */
:not(pre)>code[class*="language-"] {
padding: .1em;
border-radius: .3em;
white-space: normal;
}
.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
color: slategray;
}
.token.punctuation {
color: #999;
}
.namespace {
opacity: .7;
}
.token.property,
.token.tag,
.token.boolean,
.token.number,
.token.constant,
.token.symbol,
.token.deleted {
color: #905;
}
.token.selector,
.token.attr-name,
.token.string,
.token.char,
.token.builtin,
.token.inserted {
color: #690;
}
.token.operator,
.token.entity,
.token.url,
.language-css .token.string,
.style .token.string {
color: #9a6e3a;
background: hsla(0, 0%, 100%, .5);
}
.token.atrule,
.token.attr-value,
.token.keyword {
color: #07a;
}
.token.function,
.token.class-name {
color: #DD4A68;
}
.token.regex,
.token.important,
.token.variable {
color: #e90;
}
.token.important,
.token.bold {
font-weight: bold;
}
.token.italic {
font-style: italic;
}
.token.entity {
cursor: help;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>iconfont Demo</title>
<link rel="shortcut icon" href="//img.alicdn.com/imgextra/i2/O1CN01ZyAlrn1MwaMhqz36G_!!6000000001499-73-tps-64-64.ico" type="image/x-icon"/>
<link rel="icon" type="image/svg+xml" href="//img.alicdn.com/imgextra/i4/O1CN01EYTRnJ297D6vehehJ_!!6000000008020-55-tps-64-64.svg"/>
<link rel="stylesheet" href="https://g.alicdn.com/thx/cube/1.3.2/cube.min.css">
<link rel="stylesheet" href="demo.css">
<link rel="stylesheet" href="iconfont.css">
<script src="iconfont.js"></script>
<!-- jQuery -->
<script src="https://a1.alicdn.com/oss/uploads/2018/12/26/7bfddb60-08e8-11e9-9b04-53e73bb6408b.js"></script>
<!-- 代码高亮 -->
<script src="https://a1.alicdn.com/oss/uploads/2018/12/26/a3f714d0-08e6-11e9-8a15-ebf944d7534c.js"></script>
<style>
.main .logo {
margin-top: 0;
height: auto;
}
.main .logo a {
display: flex;
align-items: center;
}
.main .logo .sub-title {
margin-left: 0.5em;
font-size: 22px;
color: #fff;
background: linear-gradient(-45deg, #3967FF, #B500FE);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
</style>
</head>
<body>
<div class="main">
<h1 class="logo"><a href="https://www.iconfont.cn/" title="iconfont 首页" target="_blank">
<img width="200" src="https://img.alicdn.com/imgextra/i3/O1CN01Mn65HV1FfSEzR6DKv_!!6000000000514-55-tps-228-59.svg">
</a></h1>
<div class="nav-tabs">
<ul id="tabs" class="dib-box">
<li class="dib active"><span>Unicode</span></li>
<li class="dib"><span>Font class</span></li>
<li class="dib"><span>Symbol</span></li>
</ul>
<a href="https://www.iconfont.cn/manage/index?manage_type=myprojects&projectId=1782818" target="_blank" class="nav-more">查看项目</a>
</div>
<div class="tab-container">
<div class="content unicode" style="display: block;">
<ul class="icon_lists dib-box">
<li class="dib">
<span class="icon iconfont">&#xe7de;</span>
<div class="name">table</div>
<div class="code-name">&amp;#xe7de;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe60a;</span>
<div class="name">拆分行</div>
<div class="code-name">&amp;#xe60a;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe60b;</span>
<div class="name">拆分列</div>
<div class="code-name">&amp;#xe60b;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe60d;</span>
<div class="name">拆分</div>
<div class="code-name">&amp;#xe60d;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe6ce;</span>
<div class="name">行追加</div>
<div class="code-name">&amp;#xe6ce;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe6cf;</span>
<div class="name">列追加</div>
<div class="code-name">&amp;#xe6cf;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe8a2;</span>
<div class="name">插入行</div>
<div class="code-name">&amp;#xe8a2;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe8a4;</span>
<div class="name">插入列</div>
<div class="code-name">&amp;#xe8a4;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe66a;</span>
<div class="name">上下合并</div>
<div class="code-name">&amp;#xe66a;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe66b;</span>
<div class="name">左右合并</div>
<div class="code-name">&amp;#xe66b;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe609;</span>
<div class="name">treeselect</div>
<div class="code-name">&amp;#xe609;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe66e;</span>
<div class="name">Barcode</div>
<div class="code-name">&amp;#xe66e;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe612;</span>
<div class="name">bar-code</div>
<div class="code-name">&amp;#xe612;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe692;</span>
<div class="name">Dialog</div>
<div class="code-name">&amp;#xe692;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe6b5;</span>
<div class="name">Organization Chart</div>
<div class="code-name">&amp;#xe6b5;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe697;</span>
<div class="name">级联</div>
<div class="code-name">&amp;#xe697;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe666;</span>
<div class="name">Color picker</div>
<div class="code-name">&amp;#xe666;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe75f;</span>
<div class="name">省市区</div>
<div class="code-name">&amp;#xe75f;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe6fb;</span>
<div class="name">文本</div>
<div class="code-name">&amp;#xe6fb;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe8fb;</span>
<div class="name">link</div>
<div class="code-name">&amp;#xe8fb;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe61c;</span>
<div class="name">警告</div>
<div class="code-name">&amp;#xe61c;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe68e;</span>
<div class="name">alert</div>
<div class="code-name">&amp;#xe68e;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe608;</span>
<div class="name">gitee</div>
<div class="code-name">&amp;#xe608;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe607;</span>
<div class="name">Logo GitHub</div>
<div class="code-name">&amp;#xe607;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe82a;</span>
<div class="name">dialog</div>
<div class="code-name">&amp;#xe82a;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe68a;</span>
<div class="name">地图</div>
<div class="code-name">&amp;#xe68a;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe7bd;</span>
<div class="name">编辑器</div>
<div class="code-name">&amp;#xe7bd;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe6b3;</span>
<div class="name">divider</div>
<div class="code-name">&amp;#xe6b3;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe642;</span>
<div class="name">按钮</div>
<div class="code-name">&amp;#xe642;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe648;</span>
<div class="name">按钮</div>
<div class="code-name">&amp;#xe648;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe705;</span>
<div class="name">按钮</div>
<div class="code-name">&amp;#xe705;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe602;</span>
<div class="name">加号</div>
<div class="code-name">&amp;#xe602;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe600;</span>
<div class="name">workbench_personal center_secondary password</div>
<div class="code-name">&amp;#xe600;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe822;</span>
<div class="name">lock</div>
<div class="code-name">&amp;#xe822;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe622;</span>
<div class="name">HTML</div>
<div class="code-name">&amp;#xe622;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe61a;</span>
<div class="name">时间</div>
<div class="code-name">&amp;#xe61a;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe60f;</span>
<div class="name">chart-area</div>
<div class="code-name">&amp;#xe60f;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe601;</span>
<div class="name">时间范围</div>
<div class="code-name">&amp;#xe601;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe629;</span>
<div class="name">多选项</div>
<div class="code-name">&amp;#xe629;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe7b2;</span>
<div class="name">日期</div>
<div class="code-name">&amp;#xe7b2;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe7fe;</span>
<div class="name">编辑器</div>
<div class="code-name">&amp;#xe7fe;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe620;</span>
<div class="name">滑块</div>
<div class="code-name">&amp;#xe620;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe802;</span>
<div class="name">表格</div>
<div class="code-name">&amp;#xe802;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe7dc;</span>
<div class="name">stream list</div>
<div class="code-name">&amp;#xe7dc;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe619;</span>
<div class="name">input</div>
<div class="code-name">&amp;#xe619;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe62f;</span>
<div class="name">开关 关</div>
<div class="code-name">&amp;#xe62f;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe829;</span>
<div class="name">评分</div>
<div class="code-name">&amp;#xe829;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe624;</span>
<div class="name">附 件</div>
<div class="code-name">&amp;#xe624;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe621;</span>
<div class="name">html</div>
<div class="code-name">&amp;#xe621;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe614;</span>
<div class="name">编辑器</div>
<div class="code-name">&amp;#xe614;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe603;</span>
<div class="name">textarea</div>
<div class="code-name">&amp;#xe603;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe604;</span>
<div class="name">定位</div>
<div class="code-name">&amp;#xe604;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe69d;</span>
<div class="name">栅格</div>
<div class="code-name">&amp;#xe69d;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe73e;</span>
<div class="name">分割线</div>
<div class="code-name">&amp;#xe73e;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe73b;</span>
<div class="name">日期范围</div>
<div class="code-name">&amp;#xe73b;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe63c;</span>
<div class="name">下 拉</div>
<div class="code-name">&amp;#xe63c;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe605;</span>
<div class="name">单选</div>
<div class="code-name">&amp;#xe605;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe606;</span>
<div class="name">chart-line</div>
<div class="code-name">&amp;#xe606;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe6a7;</span>
<div class="name">计数器</div>
<div class="code-name">&amp;#xe6a7;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe6b4;</span>
<div class="name">tab</div>
<div class="code-name">&amp;#xe6b4;</div>
</li>
</ul>
<div class="article markdown">
<h2 id="unicode-">Unicode 引用</h2>
<hr>
<p>Unicode 是字体在网页端最原始的应用方式,特点是:</p>
<ul>
<li>支持按字体的方式去动态调整图标大小,颜色等等。</li>
<li>默认情况下不支持多色,直接添加多色图标会自动去色。</li>
</ul>
<blockquote>
<p>注意:新版 iconfont 支持两种方式引用多色图标:SVG symbol 引用方式和彩色字体图标模式。(使用彩色字体图标需要在「编辑项目」中开启「彩色」选项后并重新生成。)</p>
</blockquote>
<p>Unicode 使用步骤如下:</p>
<h3 id="-font-face">第一步:拷贝项目下面生成的 <code>@font-face</code></h3>
<pre><code class="language-css"
>@font-face {
font-family: 'iconfont';
src: url('iconfont.woff2?t=1636125596282') format('woff2'),
url('iconfont.woff?t=1636125596282') format('woff'),
url('iconfont.ttf?t=1636125596282') format('truetype');
}
</code></pre>
<h3 id="-iconfont-">第二步:定义使用 iconfont 的样式</h3>
<pre><code class="language-css"
>.iconfont {
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
</code></pre>
<h3 id="-">第三步:挑选相应图标并获取字体编码,应用于页面</h3>
<pre>
<code class="language-html"
>&lt;span class="iconfont"&gt;&amp;#x33;&lt;/span&gt;
</code></pre>
<blockquote>
<p>"iconfont" 是你项目下的 font-family。可以通过编辑项目查看,默认是 "iconfont"。</p>
</blockquote>
</div>
</div>
<div class="content font-class">
<ul class="icon_lists dib-box">
<li class="dib">
<span class="icon iconfont icon-table_layout"></span>
<div class="name">
table
</div>
<div class="code-name">.icon-table_layout
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-chaifenhang"></span>
<div class="name">
拆分行
</div>
<div class="code-name">.icon-chaifenhang
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-chaifenlie"></span>
<div class="name">
拆分列
</div>
<div class="code-name">.icon-chaifenlie
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-chaifen"></span>
<div class="name">
拆分
</div>
<div class="code-name">.icon-chaifen
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-zhuijiahang"></span>
<div class="name">
行追加
</div>
<div class="code-name">.icon-zhuijiahang
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-zhuijialie"></span>
<div class="name">
列追加
</div>
<div class="code-name">.icon-zhuijialie
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-charuhang"></span>
<div class="name">
插入行
</div>
<div class="code-name">.icon-charuhang
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-charulie"></span>
<div class="name">
插入列
</div>
<div class="code-name">.icon-charulie
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-shangxiahebing"></span>
<div class="name">
上下合并
</div>
<div class="code-name">.icon-shangxiahebing
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-zuoyouhebing"></span>
<div class="name">
左右合并
</div>
<div class="code-name">.icon-zuoyouhebing
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-treeselect"></span>
<div class="name">
treeselect
</div>
<div class="code-name">.icon-treeselect
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-barcode2"></span>
<div class="name">
Barcode
</div>
<div class="code-name">.icon-barcode2
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-barcode"></span>
<div class="name">
bar-code
</div>
<div class="code-name">.icon-barcode
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-dialog"></span>
<div class="name">
Dialog
</div>
<div class="code-name">.icon-dialog
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-address"></span>
<div class="name">
Organization Chart
</div>
<div class="code-name">.icon-address
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-cascader"></span>
<div class="name">
级联
</div>
<div class="code-name">.icon-cascader
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-colorpicker"></span>
<div class="name">
Color picker
</div>
<div class="code-name">.icon-colorpicker
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-shengshiqu"></span>
<div class="name">
省市区
</div>
<div class="code-name">.icon-shengshiqu
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-text"></span>
<div class="name">
文本
</div>
<div class="code-name">.icon-text
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-link"></span>
<div class="name">
link
</div>
<div class="code-name">.icon-link
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-alert"></span>
<div class="name">
警告
</div>
<div class="code-name">.icon-alert
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-alert1"></span>
<div class="name">
alert
</div>
<div class="code-name">.icon-alert1
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-gitee"></span>
<div class="name">
gitee
</div>
<div class="code-name">.icon-gitee
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-github"></span>
<div class="name">
Logo GitHub
</div>
<div class="code-name">.icon-github
</div>
</li>
<li class="dib">
<span class="icon iconfont icondialog"></span>
<div class="name">
dialog
</div>
<div class="code-name">.icondialog
</div>
</li>
<li class="dib">
<span class="icon iconfont icon_map"></span>
<div class="name">
地图
</div>
<div class="code-name">.icon_map
</div>
</li>
<li class="dib">
<span class="icon iconfont iconbianjiqi"></span>
<div class="name">
编辑器
</div>
<div class="code-name">.iconbianjiqi
</div>
</li>
<li class="dib">
<span class="icon iconfont icondivider"></span>
<div class="name">
divider
</div>
<div class="code-name">.icondivider
</div>
</li>
<li class="dib">
<span class="icon iconfont iconanniu"></span>
<div class="name">
按钮
</div>
<div class="code-name">.iconanniu
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-button"></span>
<div class="name">
按钮
</div>
<div class="code-name">.icon-button
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-button1"></span>
<div class="name">
按钮
</div>
<div class="code-name">.icon-button1
</div>
</li>
<li class="dib">
<span class="icon iconfont iconadd"></span>
<div class="name">
加号
</div>
<div class="code-name">.iconadd
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-password"></span>
<div class="name">
workbench_personal center_secondary password
</div>
<div class="code-name">.icon-password
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-lock"></span>
<div class="name">
lock
</div>
<div class="code-name">.icon-lock
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-html"></span>
<div class="name">
HTML
</div>
<div class="code-name">.icon-html
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-time"></span>
<div class="name">
时间
</div>
<div class="code-name">.icon-time
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-chart1"></span>
<div class="name">
chart-area
</div>
<div class="code-name">.icon-chart1
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-timerange"></span>
<div class="name">
时间范围
</div>
<div class="code-name">.icon-timerange
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-checkbox"></span>
<div class="name">
多选项
</div>
<div class="code-name">.icon-checkbox
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-date"></span>
<div class="name">
日期
</div>
<div class="code-name">.icon-date
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-setting"></span>
<div class="name">
编辑器
</div>
<div class="code-name">.icon-setting
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-slider"></span>
<div class="name">
滑块
</div>
<div class="code-name">.icon-slider
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-table"></span>
<div class="name">
表格
</div>
<div class="code-name">.icon-table
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-list"></span>
<div class="name">
stream list
</div>
<div class="code-name">.icon-list
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-input"></span>
<div class="name">
input
</div>
<div class="code-name">.icon-input
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-switch"></span>
<div class="name">
开关 关
</div>
<div class="code-name">.icon-switch
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-rate"></span>
<div class="name">
评分
</div>
<div class="code-name">.icon-rate
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-att"></span>
<div class="name">
附 件
</div>
<div class="code-name">.icon-att
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-doc"></span>
<div class="name">
html
</div>
<div class="code-name">.icon-doc
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-editor"></span>
<div class="name">
编辑器
</div>
<div class="code-name">.icon-editor
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-textarea"></span>
<div class="name">
textarea
</div>
<div class="code-name">.icon-textarea
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-location"></span>
<div class="name">
定位
</div>
<div class="code-name">.icon-location
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-col"></span>
<div class="name">
栅格
</div>
<div class="code-name">.icon-col
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-divider"></span>
<div class="name">
分割线
</div>
<div class="code-name">.icon-divider
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-daterange"></span>
<div class="name">
日期范围
</div>
<div class="code-name">.icon-daterange
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-select"></span>
<div class="name">
下 拉
</div>
<div class="code-name">.icon-select
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-radio"></span>
<div class="name">
单选
</div>
<div class="code-name">.icon-radio
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-chart"></span>
<div class="name">
chart-line
</div>
<div class="code-name">.icon-chart
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-inputNumber"></span>
<div class="name">
计数器
</div>
<div class="code-name">.icon-inputNumber
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-tab"></span>
<div class="name">
tab
</div>
<div class="code-name">.icon-tab
</div>
</li>
</ul>
<div class="article markdown">
<h2 id="font-class-">font-class 引用</h2>
<hr>
<p>font-class 是 Unicode 使用方式的一种变种,主要是解决 Unicode 书写不直观,语意不明确的问题。</p>
<p>与 Unicode 使用方式相比,具有如下特点:</p>
<ul>
<li>相比于 Unicode 语意明确,书写更直观。可以很容易分辨这个 icon 是什么。</li>
<li>因为使用 class 来定义图标,所以当要替换图标时,只需要修改 class 里面的 Unicode 引用。</li>
</ul>
<p>使用步骤如下:</p>
<h3 id="-fontclass-">第一步:引入项目下面生成的 fontclass 代码:</h3>
<pre><code class="language-html">&lt;link rel="stylesheet" href="./iconfont.css"&gt;
</code></pre>
<h3 id="-">第二步:挑选相应图标并获取类名,应用于页面:</h3>
<pre><code class="language-html">&lt;span class="iconfont iconxxx"&gt;&lt;/span&gt;
</code></pre>
<blockquote>
<p>"
iconfont" 是你项目下的 font-family。可以通过编辑项目查看,默认是 "iconfont"。</p>
</blockquote>
</div>
</div>
<div class="content symbol">
<ul class="icon_lists dib-box">
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-table_layout"></use>
</svg>
<div class="name">table</div>
<div class="code-name">#icon-table_layout</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-chaifenhang"></use>
</svg>
<div class="name">拆分行</div>
<div class="code-name">#icon-chaifenhang</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-chaifenlie"></use>
</svg>
<div class="name">拆分列</div>
<div class="code-name">#icon-chaifenlie</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-chaifen"></use>
</svg>
<div class="name">拆分</div>
<div class="code-name">#icon-chaifen</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-zhuijiahang"></use>
</svg>
<div class="name">行追加</div>
<div class="code-name">#icon-zhuijiahang</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-zhuijialie"></use>
</svg>
<div class="name">列追加</div>
<div class="code-name">#icon-zhuijialie</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-charuhang"></use>
</svg>
<div class="name">插入行</div>
<div class="code-name">#icon-charuhang</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-charulie"></use>
</svg>
<div class="name">插入列</div>
<div class="code-name">#icon-charulie</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-shangxiahebing"></use>
</svg>
<div class="name">上下合并</div>
<div class="code-name">#icon-shangxiahebing</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-zuoyouhebing"></use>
</svg>
<div class="name">左右合并</div>
<div class="code-name">#icon-zuoyouhebing</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-treeselect"></use>
</svg>
<div class="name">treeselect</div>
<div class="code-name">#icon-treeselect</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-barcode2"></use>
</svg>
<div class="name">Barcode</div>
<div class="code-name">#icon-barcode2</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-barcode"></use>
</svg>
<div class="name">bar-code</div>
<div class="code-name">#icon-barcode</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-dialog"></use>
</svg>
<div class="name">Dialog</div>
<div class="code-name">#icon-dialog</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-address"></use>
</svg>
<div class="name">Organization Chart</div>
<div class="code-name">#icon-address</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-cascader"></use>
</svg>
<div class="name">级联</div>
<div class="code-name">#icon-cascader</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-colorpicker"></use>
</svg>
<div class="name">Color picker</div>
<div class="code-name">#icon-colorpicker</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-shengshiqu"></use>
</svg>
<div class="name">省市区</div>
<div class="code-name">#icon-shengshiqu</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-text"></use>
</svg>
<div class="name">文本</div>
<div class="code-name">#icon-text</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-link"></use>
</svg>
<div class="name">link</div>
<div class="code-name">#icon-link</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-alert"></use>
</svg>
<div class="name">警告</div>
<div class="code-name">#icon-alert</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-alert1"></use>
</svg>
<div class="name">alert</div>
<div class="code-name">#icon-alert1</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-gitee"></use>
</svg>
<div class="name">gitee</div>
<div class="code-name">#icon-gitee</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-github"></use>
</svg>
<div class="name">Logo GitHub</div>
<div class="code-name">#icon-github</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icondialog"></use>
</svg>
<div class="name">dialog</div>
<div class="code-name">#icondialog</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon_map"></use>
</svg>
<div class="name">地图</div>
<div class="code-name">#icon_map</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#iconbianjiqi"></use>
</svg>
<div class="name">编辑器</div>
<div class="code-name">#iconbianjiqi</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icondivider"></use>
</svg>
<div class="name">divider</div>
<div class="code-name">#icondivider</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#iconanniu"></use>
</svg>
<div class="name">按钮</div>
<div class="code-name">#iconanniu</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-button"></use>
</svg>
<div class="name">按钮</div>
<div class="code-name">#icon-button</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-button1"></use>
</svg>
<div class="name">按钮</div>
<div class="code-name">#icon-button1</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#iconadd"></use>
</svg>
<div class="name">加号</div>
<div class="code-name">#iconadd</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-password"></use>
</svg>
<div class="name">workbench_personal center_secondary password</div>
<div class="code-name">#icon-password</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-lock"></use>
</svg>
<div class="name">lock</div>
<div class="code-name">#icon-lock</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-html"></use>
</svg>
<div class="name">HTML</div>
<div class="code-name">#icon-html</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-time"></use>
</svg>
<div class="name">时间</div>
<div class="code-name">#icon-time</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-chart1"></use>
</svg>
<div class="name">chart-area</div>
<div class="code-name">#icon-chart1</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-timerange"></use>
</svg>
<div class="name">时间范围</div>
<div class="code-name">#icon-timerange</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-checkbox"></use>
</svg>
<div class="name">多选项</div>
<div class="code-name">#icon-checkbox</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-date"></use>
</svg>
<div class="name">日期</div>
<div class="code-name">#icon-date</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-setting"></use>
</svg>
<div class="name">编辑器</div>
<div class="code-name">#icon-setting</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-slider"></use>
</svg>
<div class="name">滑块</div>
<div class="code-name">#icon-slider</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-table"></use>
</svg>
<div class="name">表格</div>
<div class="code-name">#icon-table</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-list"></use>
</svg>
<div class="name">stream list</div>
<div class="code-name">#icon-list</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-input"></use>
</svg>
<div class="name">input</div>
<div class="code-name">#icon-input</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-switch"></use>
</svg>
<div class="name">开关 关</div>
<div class="code-name">#icon-switch</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-rate"></use>
</svg>
<div class="name">评分</div>
<div class="code-name">#icon-rate</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-att"></use>
</svg>
<div class="name">附 件</div>
<div class="code-name">#icon-att</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-doc"></use>
</svg>
<div class="name">html</div>
<div class="code-name">#icon-doc</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-editor"></use>
</svg>
<div class="name">编辑器</div>
<div class="code-name">#icon-editor</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-textarea"></use>
</svg>
<div class="name">textarea</div>
<div class="code-name">#icon-textarea</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-location"></use>
</svg>
<div class="name">定位</div>
<div class="code-name">#icon-location</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-col"></use>
</svg>
<div class="name">栅格</div>
<div class="code-name">#icon-col</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-divider"></use>
</svg>
<div class="name">分割线</div>
<div class="code-name">#icon-divider</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-daterange"></use>
</svg>
<div class="name">日期范围</div>
<div class="code-name">#icon-daterange</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-select"></use>
</svg>
<div class="name">下 拉</div>
<div class="code-name">#icon-select</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-radio"></use>
</svg>
<div class="name">单选</div>
<div class="code-name">#icon-radio</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-chart"></use>
</svg>
<div class="name">chart-line</div>
<div class="code-name">#icon-chart</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-inputNumber"></use>
</svg>
<div class="name">计数器</div>
<div class="code-name">#icon-inputNumber</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-tab"></use>
</svg>
<div class="name">tab</div>
<div class="code-name">#icon-tab</div>
</li>
</ul>
<div class="article markdown">
<h2 id="symbol-">Symbol 引用</h2>
<hr>
<p>这是一种全新的使用方式,应该说这才是未来的主流,也是平台目前推荐的用法。相关介绍可以参考这篇<a href="">文章</a>
这种用法其实是做了一个 SVG 的集合,与另外两种相比具有如下特点:</p>
<ul>
<li>支持多色图标了,不再受单色限制。</li>
<li>通过一些技巧,支持像字体那样,通过 <code>font-size</code>, <code>color</code> 来调整样式。</li>
<li>兼容性较差,支持 IE9+,及现代浏览器。</li>
<li>浏览器渲染 SVG 的性能一般,还不如 png。</li>
</ul>
<p>使用步骤如下:</p>
<h3 id="-symbol-">第一步:引入项目下面生成的 symbol 代码:</h3>
<pre><code class="language-html">&lt;script src="./iconfont.js"&gt;&lt;/script&gt;
</code></pre>
<h3 id="-css-">第二步:加入通用 CSS 代码(引入一次就行):</h3>
<pre><code class="language-html">&lt;style&gt;
.icon {
width: 1em;
height: 1em;
vertical-align: -0.15em;
fill: currentColor;
overflow: hidden;
}
&lt;/style&gt;
</code></pre>
<h3 id="-">第三步:挑选相应图标并获取类名,应用于页面:</h3>
<pre><code class="language-html">&lt;svg class="icon" aria-hidden="true"&gt;
&lt;use xlink:href="#icon-xxx"&gt;&lt;/use&gt;
&lt;/svg&gt;
</code></pre>
</div>
</div>
</div>
</div>
<script>
$(document).ready(function () {
$('.tab-container .content:first').show()
$('#tabs li').click(function (e) {
var tabContent = $('.tab-container .content')
var index = $(this).index()
if ($(this).hasClass('active')) {
return
} else {
$('#tabs li').removeClass('active')
$(this).addClass('active')
tabContent.hide().eq(index).fadeIn()
}
})
})
</script>
</body>
</html>
@font-face {
font-family: "iconfont"; /* Project id 1782818 */
src: url('iconfont.woff2?t=1636125596282') format('woff2'),
url('iconfont.woff?t=1636125596282') format('woff'),
url('iconfont.ttf?t=1636125596282') format('truetype');
}
.iconfont {
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-table_layout:before {
content: "\e7de";
}
.icon-chaifenhang:before {
content: "\e60a";
}
.icon-chaifenlie:before {
content: "\e60b";
}
.icon-chaifen:before {
content: "\e60d";
}
.icon-zhuijiahang:before {
content: "\e6ce";
}
.icon-zhuijialie:before {
content: "\e6cf";
}
.icon-charuhang:before {
content: "\e8a2";
}
.icon-charulie:before {
content: "\e8a4";
}
.icon-shangxiahebing:before {
content: "\e66a";
}
.icon-zuoyouhebing:before {
content: "\e66b";
}
.icon-treeselect:before {
content: "\e609";
}
.icon-barcode2:before {
content: "\e66e";
}
.icon-barcode:before {
content: "\e612";
}
.icon-dialog:before {
content: "\e692";
}
.icon-address:before {
content: "\e6b5";
}
.icon-cascader:before {
content: "\e697";
}
.icon-colorpicker:before {
content: "\e666";
}
.icon-shengshiqu:before {
content: "\e75f";
}
.icon-text:before {
content: "\e6fb";
}
.icon-link:before {
content: "\e8fb";
}
.icon-alert:before {
content: "\e61c";
}
.icon-alert1:before {
content: "\e68e";
}
.icon-gitee:before {
content: "\e608";
}
.icon-github:before {
content: "\e607";
}
.icondialog:before {
content: "\e82a";
}
.icon_map:before {
content: "\e68a";
}
.iconbianjiqi:before {
content: "\e7bd";
}
.icondivider:before {
content: "\e6b3";
}
.iconanniu:before {
content: "\e642";
}
.icon-button:before {
content: "\e648";
}
.icon-button1:before {
content: "\e705";
}
.iconadd:before {
content: "\e602";
}
.icon-password:before {
content: "\e600";
}
.icon-lock:before {
content: "\e822";
}
.icon-html:before {
content: "\e622";
}
.icon-time:before {
content: "\e61a";
}
.icon-chart1:before {
content: "\e60f";
}
.icon-timerange:before {
content: "\e601";
}
.icon-checkbox:before {
content: "\e629";
}
.icon-date:before {
content: "\e7b2";
}
.icon-setting:before {
content: "\e7fe";
}
.icon-slider:before {
content: "\e620";
}
.icon-table:before {
content: "\e802";
}
.icon-list:before {
content: "\e7dc";
}
.icon-input:before {
content: "\e619";
}
.icon-switch:before {
content: "\e62f";
}
.icon-rate:before {
content: "\e829";
}
.icon-att:before {
content: "\e624";
}
.icon-doc:before {
content: "\e621";
}
.icon-editor:before {
content: "\e614";
}
.icon-textarea:before {
content: "\e603";
}
.icon-location:before {
content: "\e604";
}
.icon-col:before {
content: "\e69d";
}
.icon-divider:before {
content: "\e73e";
}
.icon-daterange:before {
content: "\e73b";
}
.icon-select:before {
content: "\e63c";
}
.icon-radio:before {
content: "\e605";
}
.icon-chart:before {
content: "\e606";
}
.icon-inputNumber:before {
content: "\e6a7";
}
.icon-tab:before {
content: "\e6b4";
}
!function(h){var c,a,l,v,t,z='<svg><symbol id="icon-table_layout" viewBox="0 0 1024 1024"><path d="M928 160H96c-17.7 0-32 14.3-32 32v640c0 17.7 14.3 32 32 32h832c17.7 0 32-14.3 32-32V192c0-17.7-14.3-32-32-32z m-40 208H676V232h212v136z m0 224H676V432h212v160zM412 432h200v160H412V432z m200-64H412V232h200v136z m-476 64h212v160H136V432z m0-200h212v136H136V232z m0 424h212v136H136V656z m276 0h200v136H412V656z m476 136H676V656h212v136z" ></path></symbol><symbol id="icon-chaifenhang" viewBox="0 0 1378 1024"><path d="M1193.49038455 207.91025607v778.84615449H317.28846179V207.91025607h876.20192276m0-32.45192275H317.28846179a32.45192275 32.45192275 0 0 0-32.45192358 32.45192276v778.84615449a32.45192275 32.45192275 0 0 0 32.45192358 32.45192275h876.20192276a32.45192275 32.45192275 0 0 0 32.45192276-32.45192275V207.91025607a32.45192275 32.45192275 0 0 0-32.45192276-32.45192275z" fill="#4D4D4D" ></path><path d="M317.28846179 662.23717966h876.20192276v32.45192277H317.28846179zM317.28846179 824.49679511h876.20192276v32.45192276H317.28846179zM317.28846179 337.71794877h876.20192276v32.45192276H317.28846179z" fill="#B3B3B3" ></path><path d="M544.45192275 207.91025607v778.84615449h-32.45192275V207.91025607zM771.61538455 207.91025607v778.84615449h-32.45192276V207.91025607zM998.77884634 207.91025607v778.84615449h-32.45192359V207.91025607z" fill="#B3B3B3" ></path><path d="M301.0625 353.94391057m16.22596179-1e-8l876.20192276 0q16.22596179 0 16.22596179 16.22596097l0 292.06730813q0 16.22596179-16.22596179 16.22596098l-876.20192276 0q-16.22596179 0-16.22596179-16.22596098l0-292.06730813q0-16.22596179 16.22596179-16.22596097Z" fill="#05AFC8" ></path><path d="M1193.49038455 370.16987153v292.06730813H317.28846179V370.16987153h876.20192276m0-32.45192276H317.28846179a32.45192275 32.45192275 0 0 0-32.45192358 32.45192276v292.06730813a32.45192275 32.45192275 0 0 0 32.45192358 32.45192276h876.20192276a32.45192275 32.45192275 0 0 0 32.45192276-32.45192276V370.16987153a32.45192275 32.45192275 0 0 0-32.45192276-32.45192276z" fill="#4D4D4D" ></path><path d="M171.25480732 305.266026L90.125 402.62179511h162.25961545L171.25480732 305.266026z" fill="#05AFC8" ></path><path d="M138.80288455 402.62179511m1.29807724 0l62.30769187 0q1.29807724 0 1.29807724 1.29807642l0 62.30769268q0 1.29807724-1.29807724 1.29807643l-62.30769187 0q-1.29807724 0-1.29807724-1.29807642l0-62.30769269q0-1.29807724 1.29807724-1.29807642Z" fill="#05AFC8" ></path><path d="M171.25480732 727.14102601L90.125 629.78525607h162.25961545l-81.12980814 97.35576993z" fill="#05AFC8" ></path><path d="M138.80288455 564.88141057m1.29807724 0l62.30769187 0q1.29807724 0 1.29807724 1.29807641l0 62.30769268q0 1.29807724-1.29807724 1.29807641l-62.30769187 0q-1.29807724 0-1.29807724-1.29807641l0-62.30769268q0-1.29807724 1.29807724-1.29807642Z" fill="#05AFC8" ></path><path d="M317.28846179 499.97756421h876.20192276v32.45192277H317.28846179z" fill="#B3B3B3" ></path></symbol><symbol id="icon-chaifenlie" viewBox="0 0 1024 1024"><path d="M944 224v768H80V224h864m0-32H80a32 32 0 0 0-32 32v768a32 32 0 0 0 32 32h864a32 32 0 0 0 32-32V224a32 32 0 0 0-32-32z" fill="#4D4D4D" ></path><path d="M80 512h864v32H80zM80 672h864v32H80zM80 832h864v32H80zM80 352h864v32H80z" fill="#B3B3B3" ></path><path d="M304 224v768H272V224zM752 224v768h-32V224z" fill="#B3B3B3" ></path><path d="M288 208m16 0l416 0q16 0 16 16l0 768q0 16-16 16l-416 0q-16 0-16-16l0-768q0-16 16-16Z" fill="#05AFC8" ></path><path d="M720 224v768H304V224h416m0-32H304a32 32 0 0 0-32 32v768a32 32 0 0 0 32 32h416a32 32 0 0 0 32-32V224a32 32 0 0 0-32-32z" fill="#4D4D4D" ></path><path d="M720 80L624 0v160l96-80z" fill="#05AFC8" ></path><path d="M624 48m0 1.28l0 61.44q0 1.28-1.28 1.28l-61.44 0q-1.28 0-1.28-1.28l0-61.44q0-1.28 1.28-1.28l61.44 0q1.28 0 1.28 1.28Z" fill="#05AFC8" ></path><path d="M304 80L400 0v160L304 80z" fill="#05AFC8" ></path><path d="M464 48m0 1.28l0 61.44q0 1.28-1.28 1.28l-61.44 0q-1.28 0-1.28-1.28l0-61.44q0-1.28 1.28-1.28l61.44 0q1.28 0 1.28 1.28Z" fill="#05AFC8" ></path><path d="M528 224v768h-32V224z" fill="#B3B3B3" ></path></symbol><symbol id="icon-chaifen" viewBox="0 0 1024 1024"><path d="M59.448889 133.575111m56.888889 0l227.555555 0q56.888889 0 56.888889 56.888889l0 625.777778q0 56.888889-56.888889 56.888889l-227.555555 0q-56.888889 0-56.888889-56.888889l0-625.777778q0-56.888889 56.888889-56.888889Z" ></path><path d="M628.337778 133.575111m56.888889 0l227.555555 0q56.888889 0 56.888889 56.888889l0 625.777778q0 56.888889-56.888889 56.888889l-227.555555 0q-56.888889 0-56.888889-56.888889l0-625.777778q0-56.888889 56.888889-56.888889Z" ></path><path d="M487.879111 102.741333h56.888889v113.777778h-56.888889v-113.777778z m0 227.555556h56.888889v113.777778h-56.888889v-113.777778z m0 227.555555h56.888889v113.777778h-56.888889v-113.777778z m0 227.555556h56.888889v113.777778h-56.888889v-113.777778z" ></path></symbol><symbol id="icon-zhuijiahang" viewBox="0 0 1024 1024"><path d="M976 529.7V289.5h-0.3v-197H0V924h664.5V529.7H976z m-311.5-36.8v-6h-1V332.7h276.3v160.2H664.5z m-42.2-160.2h5v154.2H353.4V332.7h268.9z m-585.6 0h280v154.2h-280V332.7z m0 197h274.4v154.1H36.7V529.7z m0 357.5V727h274.4v160.2H36.7z m591.1 0H353.4V727h274.4v160.2z m0-203.4H353.4V523.6h273.9v6.1h0.5v154.1z" ></path><path d="M1024 741H885.9V601.8H840V741H701.8v45.9H840V924h45.9V786.9H1024z" ></path></symbol><symbol id="icon-zhuijialie" viewBox="0 0 1024 1024"><path d="M975.7 335.7V95.5H0V927h664.5V532.7h311.2v-197zM622.3 489.8H353.4V335.7h268.9v154.1zM939 132.2v160.3H664.5V132.2H939z m-316.7 0v160.3H353.4V132.2h268.9z m5.5 758H353.4V730h274.4v160.2z m0-203.4H353.4V532.7h274.4v154.1z m36.7-190.9V335.7H939v160.2H664.5z" ></path><path d="M1024 744H885.9V604.8H840V744H701.8v45.9H840V927h45.9V789.9H1024z" ></path></symbol><symbol id="icon-charuhang" viewBox="0 0 1024 1024"><path d="M485.052632 431.157895v161.68421H107.789474V431.157895h377.263158m53.894736-53.894737H53.894737v269.473684h485.052631V377.263158zM916.210526 269.473684H269.473684V107.789474h700.631579V53.894737H215.578947v269.473684h754.526316V269.473684zM215.578947 700.631579v269.473684h754.526316v-53.894737H269.473684v-161.68421h700.631579v-53.894737zM970.105263 484.513684L852.075789 366.484211l-38.265263 38.265263L894.113684 485.052632H646.736842v53.894736h247.376842l-80.303158 80.303158 38.265263 38.265263L970.105263 539.486316l-0.538947-0.538948H970.105263V485.052632h-0.538947z" fill="#444A5C" ></path></symbol><symbol id="icon-charulie" viewBox="0 0 1024 1024"><path d="M592.842105 485.052632H431.157895V107.789474h161.68421v377.263158m53.894737 53.894736V53.894737H377.263158v485.052631h269.473684zM754.526316 916.210526V269.473684h161.68421v700.631579h53.894737V215.578947h-269.473684v754.526316h53.894737zM323.368421 215.578947H53.894737v754.526316h53.894737V269.473684h161.68421v700.631579h53.894737zM539.486316 970.105263l118.029473-118.029474-38.265263-38.265263L538.947368 894.113684V646.736842H485.052632v247.376842L404.749474 813.810526l-38.265263 38.265263L484.513684 970.105263l0.538948-0.538947V970.105263h53.894736v-0.538947z" fill="#444A5C" ></path></symbol><symbol id="icon-shangxiahebing" viewBox="0 0 1024 1024"><path d="M157.538462 590.769231h787.692307v393.846154h-157.538461v-315.076923h-551.384616v315.076923h-157.538461v-393.846154h78.769231z m78.76923-236.307693h551.384616v-315.076923h157.538461v393.846154H78.769231v-393.846154h157.538461v315.076923z m236.307693-157.538461v-157.538462h78.76923v157.538462h78.769231L512 315.076923 393.846154 196.923077h78.769231z m78.76923 630.153846v157.538462h-78.76923v-157.538462h-78.769231L512 708.923077l118.153846 118.153846h-78.769231z" ></path></symbol><symbol id="icon-zuoyouhebing" viewBox="0 0 1117 1024"><path d="M651.636364 930.909091V0h465.454545v186.181818H744.727273v651.636364h372.363636v186.181818H651.636364v-93.090909zM372.363636 837.818182V186.181818H0V0h465.454545v1024H0V837.818182h372.363636zM186.181818 558.545455H0V465.454545h186.181818V372.363636l139.636364 139.636364L186.181818 651.636364V558.545455z m744.727273-93.09091h186.181818v93.09091h-186.181818v93.090909L791.272727 512 930.909091 372.363636v93.090909z" ></path></symbol><symbol id="icon-treeselect" viewBox="0 0 1092 1024"><path d="M1023.693953 849.590152A37.914591 37.914591 0 0 1 1061.608544 887.504743v68.246264a38.217908 38.217908 0 0 1-37.914591 37.91459h-287.544257A38.217908 38.217908 0 0 1 697.628472 955.751007v-68.246264a37.914591 37.914591 0 0 1 37.914591-37.914591h287.544257m0-30.331673h-286.937624A68.246264 68.246264 0 0 0 667.296799 887.504743v68.246264a68.246264 68.246264 0 0 0 68.246264 68.246263h287.544257A68.246264 68.246264 0 0 0 1091.940217 955.751007v-68.246264a68.246264 68.246264 0 0 0-68.246264-68.246264zM1023.693953 440.112571A37.914591 37.914591 0 0 1 1061.608544 477.723845V545.970108a37.914591 37.914591 0 0 1-37.914591 37.914591h-287.544257A37.914591 37.914591 0 0 1 697.628472 545.970108v-68.246263a37.914591 37.914591 0 0 1 37.914591-37.611274h287.544257m0-30.331673h-286.937624A67.942947 67.942947 0 0 0 667.296799 477.723845V545.970108a68.246264 68.246264 0 0 0 68.246264 68.246264h287.544257A68.246264 68.246264 0 0 0 1091.940217 545.970108v-68.246263a67.942947 67.942947 0 0 0-68.246264-67.942947zM545.970108 440.112571a37.914591 37.914591 0 0 1 37.914591 37.914591V545.970108A37.914591 37.914591 0 0 1 545.970108 583.884699h-68.246263A37.914591 37.914591 0 0 1 439.809254 545.970108v-67.942946a37.914591 37.914591 0 0 1 37.914591-37.914591H545.970108m0-30.331673h-68.246263a68.246264 68.246264 0 0 0-68.246264 68.246264V545.970108a68.246264 68.246264 0 0 0 68.246264 68.246264H545.970108A68.246264 68.246264 0 0 0 614.216372 545.970108v-67.942946A68.246264 68.246264 0 0 0 545.970108 409.780898zM545.970108 849.590152a37.914591 37.914591 0 0 1 37.914591 37.914591v68.246264A38.217908 38.217908 0 0 1 545.970108 993.665597h-68.246263a38.217908 38.217908 0 0 1-37.914591-37.91459v-68.246264a37.914591 37.914591 0 0 1 37.914591-37.914591H545.970108m0-30.331673h-68.246263a68.246264 68.246264 0 0 0-68.246264 68.246264v68.246264a68.246264 68.246264 0 0 0 68.246264 68.246263H545.970108a68.246264 68.246264 0 0 0 68.246264-68.246263v-68.246264A68.246264 68.246264 0 0 0 545.970108 819.258479zM545.970108 30.331673a38.217908 38.217908 0 0 1 26.691872 11.222719 37.307957 37.307957 0 0 1 11.222719 26.691872V136.492527A37.914591 37.914591 0 0 1 545.970108 174.407118H68.246264A37.914591 37.914591 0 0 1 30.331673 136.492527V68.246264A38.217908 38.217908 0 0 1 68.246264 30.331673H545.970108m0-30.331673H68.246264A68.246264 68.246264 0 0 0 0 68.246264V136.492527a68.246264 68.246264 0 0 0 68.246264 68.246264H545.970108a67.942947 67.942947 0 0 0 48.22736-19.715588 69.45953 69.45953 0 0 0 20.018904-48.530676V68.246264a69.156214 69.156214 0 0 0-20.018904-48.22736A68.246264 68.246264 0 0 0 545.970108 0zM966.973725 30.331673L879.618508 169.55405 792.869924 30.331673h174.103801m10.616086-30.331673h-195.335972a25.781922 25.781922 0 0 0-21.535488 12.739303 24.871972 24.871972 0 0 0 0 25.175288l97.36467 155.298164a24.871972 24.871972 0 0 0 41.857708 0l97.364669-155.298164A24.568655 24.568655 0 0 0 976.679861 0z m-195.335972 0z m0 0zM136.492527 904.187163h204.738791v33.971473H136.492527zM136.492527 494.709582h204.738791v33.971473H136.492527z" ></path><path d="M136.492527 193.212755h33.971474v728.263461H136.492527z" ></path></symbol><symbol id="icon-barcode2" viewBox="0 0 1024 1024"><path d="M853.333333 887.466667H153.6c-81.92 0-136.533333-54.613333-136.533333-136.533334V273.066667c0-81.92 54.613333-136.533333 136.533333-136.533334H853.333333c81.92 0 153.6 71.68 153.6 153.6v443.733334c0 81.92-71.68 153.6-153.6 153.6zM153.6 170.666667c-61.44 0-102.4 40.96-102.4 102.4v477.866666c0 61.44 40.96 102.4 102.4 102.4H853.333333c61.44 0 119.466667-58.026667 119.466667-119.466666v-443.733334C972.8 228.693333 914.773333 170.666667 853.333333 170.666667H153.6z" fill="" ></path><path d="M204.8 716.8c-10.24 0-17.066667-6.826667-17.066667-17.066667v-409.6c0-10.24 6.826667-17.066667 17.066667-17.066666s17.066667 6.826667 17.066667 17.066666v409.6c0 10.24-6.826667 17.066667-17.066667 17.066667zM307.2 648.533333c-10.24 0-17.066667-6.826667-17.066667-17.066666v-341.333334c0-10.24 6.826667-17.066667 17.066667-17.066666s17.066667 6.826667 17.066667 17.066666v341.333334c0 10.24-6.826667 17.066667-17.066667 17.066666zM409.6 648.533333c-10.24 0-17.066667-6.826667-17.066667-17.066666v-341.333334c0-10.24 6.826667-17.066667 17.066667-17.066666s17.066667 6.826667 17.066667 17.066666v341.333334c0 10.24-6.826667 17.066667-17.066667 17.066666zM512 716.8c-10.24 0-17.066667-6.826667-17.066667-17.066667v-409.6c0-10.24 6.826667-17.066667 17.066667-17.066666s17.066667 6.826667 17.066667 17.066666v409.6c0 10.24-6.826667 17.066667-17.066667 17.066667zM614.4 648.533333c-10.24 0-17.066667-6.826667-17.066667-17.066666v-341.333334c0-10.24 6.826667-17.066667 17.066667-17.066666s17.066667 6.826667 17.066667 17.066666v341.333334c0 10.24-6.826667 17.066667-17.066667 17.066666zM716.8 648.533333c-10.24 0-17.066667-6.826667-17.066667-17.066666v-341.333334c0-10.24 6.826667-17.066667 17.066667-17.066666s17.066667 6.826667 17.066667 17.066666v341.333334c0 10.24-6.826667 17.066667-17.066667 17.066666zM819.2 716.8c-10.24 0-17.066667-6.826667-17.066667-17.066667v-409.6c0-10.24 6.826667-17.066667 17.066667-17.066666s17.066667 6.826667 17.066667 17.066666v409.6c0 10.24-6.826667 17.066667-17.066667 17.066667zM307.2 716.8c-3.413333 0-10.24-3.413333-10.24-6.826667-3.413333-3.413333-6.826667-6.826667-6.826667-10.24 0-3.413333 3.413333-10.24 6.826667-10.24 6.826667-6.826667 17.066667-6.826667 23.893333 0 3.413333 3.413333 6.826667 6.826667 6.826667 13.653334s-3.413333 10.24-6.826667 10.24-10.24 3.413333-13.653333 3.413333zM409.6 716.8c-3.413333 0-10.24-3.413333-10.24-3.413333-3.413333-3.413333-6.826667-6.826667-6.826667-13.653334s3.413333-10.24 6.826667-10.24c6.826667-6.826667 17.066667-6.826667 23.893333 0 3.413333 3.413333 3.413333 6.826667 3.413334 10.24s-3.413333 10.24-6.826667 10.24c0 3.413333-6.826667 6.826667-10.24 6.826667zM614.4 716.8c-3.413333 0-10.24-3.413333-10.24-3.413333-3.413333-3.413333-6.826667-6.826667-6.826667-13.653334s3.413333-10.24 3.413334-10.24c6.826667-6.826667 17.066667-6.826667 23.893333 0 3.413333 3.413333 6.826667 6.826667 6.826667 13.653334s-3.413333 10.24-3.413334 10.24c-3.413333 0-10.24 3.413333-13.653333 3.413333zM716.8 716.8c-3.413333 0-10.24-3.413333-13.653333-6.826667-3.413333-3.413333-3.413333-6.826667-3.413334-10.24s3.413333-10.24 6.826667-10.24c6.826667-6.826667 17.066667-6.826667 23.893333 0 3.413333 3.413333 6.826667 6.826667 6.826667 10.24s-3.413333 10.24-6.826667 10.24c-3.413333 3.413333-10.24 6.826667-13.653333 6.826667z" fill="" ></path></symbol><symbol id="icon-barcode" viewBox="0 0 1024 1024"><path d="M0 197.76h25.28v628.48H0zM103.36 197.76h125.76v628.48H103.36zM307.84 197.76h75.52v628.48H307.84zM462.4 197.76h176v628.48h-176zM717.76 197.76h75.52v628.48h-75.52zM870.72 197.76h25.6v628.48h-25.6zM973.76 197.76H1024v628.48h-50.24z" ></path></symbol><symbol id="icon-dialog" viewBox="0 0 1024 1024"><path d="M896 96H128c-35.35 0-64 28.65-64 64v704c0 35.35 28.65 64 64 64h768c35.35 0 64-28.65 64-64V160c0-35.35-28.65-64-64-64z m0 752c0 8.84-7.16 16-16 16H144c-8.84 0-16-7.16-16-16V176c0-8.84 7.16-16 16-16h736c8.84 0 16 7.16 16 16v672z" ></path><path d="M694.2 489.53c-0.55-0.53-1.12-1.04-1.7-1.52-0.63-0.52-1.28-1-1.94-1.47a31.872 31.872 0 0 0-18.41-5.84h-448.1c-2.21 0-4.37 0.22-6.45 0.65s-4.09 1.05-6.01 1.86c-1.91 0.81-3.73 1.8-5.44 2.95-0.85 0.58-1.67 1.19-2.46 1.84-0.4 0.33-0.78 0.66-1.16 1.01-0.76 0.69-1.48 1.41-2.17 2.17-0.42 0.46-0.82 0.94-1.21 1.42-0.48 0.6-0.94 1.21-1.38 1.84-0.81 1.17-1.55 2.4-2.21 3.67-0.23 0.44-0.44 0.89-0.65 1.35-1.84 4.03-2.87 8.51-2.87 13.23s1.03 9.2 2.87 13.23c0.21 0.46 0.42 0.9 0.65 1.35 0.65 1.28 1.39 2.5 2.21 3.67 0.44 0.63 0.9 1.25 1.38 1.84 0.11 0.14 0.22 0.28 0.34 0.41 1.93 2.31 4.17 4.34 6.67 6.02 0.85 0.58 1.73 1.11 2.64 1.6a31.854 31.854 0 0 0 15.25 3.86h448.1c4.67 0 9.1-1.01 13.1-2.8 0.73-0.33 1.45-0.68 2.16-1.06 1.1-0.59 2.15-1.26 3.16-1.97 1.9-1.34 3.66-2.88 5.22-4.6a31.905 31.905 0 0 0 8.36-21.57c0-8.57-3.37-16.34-8.86-22.09-0.36-0.34-0.72-0.7-1.09-1.05zM699.82 657.34c-0.65-1.28-1.39-2.5-2.21-3.67-0.44-0.63-0.9-1.25-1.38-1.84-0.11-0.14-0.22-0.28-0.34-0.41a31.833 31.833 0 0 0-6.67-6.02c-0.85-0.58-1.73-1.11-2.64-1.6a31.854 31.854 0 0 0-15.25-3.86h-447.3c-17.67 0-32 14.33-32 32a31.809 31.809 0 0 0 3.09 13.74c0.02 0.04 0.04 0.09 0.06 0.14 0.86 1.79 1.89 3.48 3.05 5.06l0.35 0.47c0.51 0.67 1.05 1.33 1.62 1.96a32.16 32.16 0 0 0 10.73 7.84 29.43 29.43 0 0 0 3.07 1.2c3.15 1.04 6.52 1.61 10.02 1.61h447.3a31.854 31.854 0 0 0 9.52-1.44c13.03-4.05 22.48-16.2 22.48-30.56 0-4.72-1.03-9.2-2.87-13.23-0.19-0.49-0.41-0.94-0.63-1.39zM823.9 264.12c-6.25-6.25-16.38-6.25-22.63 0l-33.12 33.12-33.12-33.12c-6.25-6.25-16.38-6.25-22.63 0s-6.25 16.38 0 22.63l33.12 33.12-33.12 33.12c-6.25 6.25-6.25 16.38 0 22.63 3.12 3.12 7.22 4.69 11.31 4.69s8.19-1.56 11.31-4.69l33.12-33.12 33.12 33.12c3.12 3.12 7.22 4.69 11.31 4.69s8.19-1.56 11.31-4.69c6.25-6.25 6.25-16.38 0-22.63l-33.12-33.12 33.12-33.12c6.26-6.25 6.26-16.38 0.02-22.63z" ></path></symbol><symbol id="icon-address" viewBox="0 0 1024 1024"><path d="M565.248 85.290667a96 96 0 0 1 96 96V309.333333a96 96 0 0 1-96 96h-32v85.333334h138.794667a96 96 0 0 1 95.786666 89.429333l0.213334 6.570667v32h32.042666a96 96 0 0 1 96 96v128.042666a96 96 0 0 1-96 96h-128.042666a96 96 0 0 1-96-96V714.666667a96 96 0 0 1 96-96h32v-32a32 32 0 0 0-27.648-31.701334L672.042667 554.666667H330.581333a32 32 0 0 0-31.701333 27.648l-0.298667 4.352v32h32a96 96 0 0 1 96 96v128.042666a96 96 0 0 1-96 96h-128a96 96 0 0 1-96-96V714.666667a96 96 0 0 1 96-96h32v-32a96 96 0 0 1 89.429334-95.786667l6.570666-0.213333h138.666667v-85.333334h-32.042667a96 96 0 0 1-96-96V181.290667a96 96 0 0 1 96-96h128.042667zM330.581333 682.666667h-128a32 32 0 0 0-32 32v128.042666c0 17.706667 14.293333 32 32 32h128a32 32 0 0 0 32-32V714.666667a32 32 0 0 0-32-32z m469.504 0h-128.042666a32 32 0 0 0-32 32v128.042666c0 17.706667 14.293333 32 32 32h128.042666a32 32 0 0 0 32-32V714.666667a32 32 0 0 0-32-32zM565.248 149.290667h-128.042667a32 32 0 0 0-32 32V309.333333c0 17.664 14.293333 32 32 32h128.042667a32 32 0 0 0 32-32V181.290667a32 32 0 0 0-32-32z" ></path></symbol><symbol id="icon-cascader" viewBox="0 0 1024 1024"><path d="M512 0c26.930286 0 48.762286 21.832 48.762286 48.762286v195.046857C560.762286 270.739429 538.930286 292.571429 512 292.571429H280.380571v207.237714h182.857143V438.857143c0-26.930286 21.832-48.762286 48.762286-48.762286h390.094857C929.025143 390.094857 950.857143 411.926857 950.857143 438.857143v195.048c0 26.930286-21.832 48.761143-48.762286 48.761143H512c-26.930286 0-48.762286-21.830857-48.762286-48.761143v-60.953143h-182.857143v256c0 5.771429 4.010286 10.605714 9.395429 11.868571L292.571429 841.142857h170.666285v-60.952C463.237714 753.260571 485.069714 731.428571 512 731.428571h390.094857C929.025143 731.428571 950.857143 753.260571 950.857143 780.190857v195.046857C950.857143 1002.168 929.025143 1024 902.094857 1024H512c-26.930286 0-48.762286-21.832-48.762286-48.762286V914.285714H292.571429c-44.771429 0-81.490286-34.48-85.051429-78.334857l-0.282286-6.998857V292.571429H121.905143C94.974857 292.571429 73.142857 270.739429 73.142857 243.809143V48.762286C73.142857 21.832 94.974857 0 121.905143 0H512z m365.714286 804.571429H536.380571v146.285714H877.714286V804.571429z m0-341.333715H536.380571v146.285715H877.714286v-146.285715zM487.619429 73.142857H146.285714v146.285714h341.333715V73.142857z" ></path></symbol><symbol id="icon-colorpicker" viewBox="0 0 1024 1024"><path d="M649.386667 461.653333l-8.533334 7.68-85.333333-85.333333 57.1904-56.32C602.453333 306.056533 597.333333 282.453333 597.333333 256.853333V256c0-47.223467 16.503467-87.6032 49.493334-121.173333C680.379733 101.8368 720.759467 85.333333 768 85.333333s87.313067 16.503467 120.32 49.493334C921.9072 168.3968 938.666667 208.776533 938.666667 256s-16.759467 87.330133-50.346667 120.32c-33.006933 33.570133-72.823467 50.346667-119.466667 50.346667H768c-25.0368 0-48.059733-4.5568-69.12-13.653334l-49.493333 48.64zM342.186667 768L256 853.333333h-85.333333v-84.48L256.853333 682.666667l85.333334 85.333333z" ></path><path d="M594.722133 538.743467l-23.773866-24.507734 115.968-113.408a17.032533 17.032533 0 0 1 18.7392-3.498666c18.807467 8.1408 39.799467 12.270933 62.344533 12.270933 43.1104 0 78.216533-14.7968 108.151467-45.243733C906.8032 334.2336 921.6 298.871467 921.6 256c0-42.9056-14.830933-78.592-45.346133-109.1072C846.301867 116.957867 810.9056 102.4 768 102.4c-42.973867 0-78.677333 14.574933-109.192533 44.5952C628.974933 177.322667 614.4 213.0432 614.4 256c0 23.790933 4.625067 45.1584 13.7216 64.375467a17.066667 17.066667 0 0 1-3.4304 19.473066l-100.625067 99.7376-24.132266-24.132266 43.52-43.52 12.066133 12.066133-11.9808-12.151467 48.878933-48.128A183.5008 183.5008 0 0 1 580.266667 256.853333c0-52.48 18.295467-97.262933 54.408533-133.9904C671.573333 86.562133 716.373333 68.266667 768 68.266667c51.677867 0 96.221867 18.3296 132.386133 54.493866C937.1136 159.470933 955.733333 204.305067 955.733333 256c0 51.780267-18.670933 96.3584-55.4496 132.488533C864.324267 425.079467 820.036267 443.733333 768.853333 443.733333c-23.773867 0-45.704533-3.618133-65.8944-10.786133l-48.571733 48.657067-12.680533-11.4176 11.741866 12.407466-58.7264 56.149334z" ></path><path d="M85.333333 972.8a34.133333 34.133333 0 0 1-24.132266-58.2656l85.333333-85.333333a34.133333 34.133333 0 1 1 48.264533 48.264533l-85.333333 85.333333A33.962667 33.962667 0 0 1 85.333333 972.8z m598.186667-426.666667a33.9968 33.9968 0 0 1-24.132267-10.001066l-170.666666-170.666667a34.133333 34.133333 0 1 1 48.264533-48.264533l128 128a4.727467 4.727467 0 0 1 0.4096 0.426666 5.034667 5.034667 0 0 1 0.426667 0.426667l41.813333 41.813333A34.133333 34.133333 0 0 1 683.52 546.133333z" ></path><path d="M256 870.4h-85.333333a17.066667 17.066667 0 0 1-17.066667-17.066667v-84.48c0-4.539733 1.792-8.874667 5.000533-12.066133l341.333334-341.333333a17.0496 17.0496 0 1 1 24.132266 24.132266L187.733333 775.918933V836.266667h61.252267l81.186133-80.401067 240.571734-241.425067a17.066667 17.066667 0 0 1 24.1664 24.1152L268.014933 865.467733c-3.208533 3.157333-7.509333 4.932267-12.014933 4.932267z m354.133333-353.28a17.0496 17.0496 0 0 1-12.066133-29.1328l39.901867-39.0144a17.066667 17.066667 0 0 1 22.8352 25.361067l-8.533334 7.68-30.071466 30.1056a17.015467 17.015467 0 0 1-12.066134 5.000533z" ></path><path d="M280.9856 658.517333l85.333333 85.333334-48.264533 48.2816-85.333333-85.333334z" ></path></symbol><symbol id="icon-shengshiqu" viewBox="0 0 1024 1024"><path d="M524.552258 848.929032c184.32 0 333.625806-149.966452 333.625807-333.625806s-149.966452-333.625806-333.625807-333.625807c-184.32 0-333.625806 149.966452-333.625806 333.625807s149.305806 333.625806 333.625806 333.625806m0 48.227097c-210.745806 0-381.852903-171.107097-381.852903-381.852903s171.107097-381.852903 381.852903-381.852903 381.192258 171.107097 381.192258 381.852903-170.446452 381.852903-381.192258 381.852903z" ></path><path d="M524.552258 686.410323c67.385806-70.689032 143.36-168.464516 143.36-218.673549 0-78.616774-64.082581-143.36-143.36-143.36-78.616774 0-143.36 64.082581-143.36 143.36 0.660645 50.209032 75.974194 147.984516 143.36 218.673549m0 67.385806S333.625806 572.779355 333.625806 467.736774c0-105.042581 85.223226-190.926452 190.926452-190.926451 105.042581 0 190.926452 85.223226 190.926452 190.926451 0 105.042581-190.926452 286.059355-190.926452 286.059355z" ></path><path d="M524.552258 515.303226c26.425806 0 47.566452-21.140645 47.566452-47.566452s-21.140645-47.566452-47.566452-47.566451-47.566452 21.140645-47.566452 47.566451 21.140645 47.566452 47.566452 47.566452m0 47.566451c-52.851613 0-95.132903-42.941935-95.132903-95.132903 0-52.851613 42.941935-95.132903 95.132903-95.132903 52.851613 0 95.132903 42.941935 95.132903 95.132903 0 52.851613-42.28129 95.132903-95.132903 95.132903z" ></path></symbol><symbol id="icon-text" viewBox="0 0 1058 1024"><path d="M304.542914 298.216519c-10.414219 0-18.979184-8.467636-18.979184-18.979184 0-10.414219 8.467636-18.979184 18.979184-18.979185h244.880145c10.414219 0 18.979184 8.467636 18.979184 18.979185 0 10.414219-8.467636 18.979184-18.979184 18.979184H304.542914z" ></path><path d="M304.542914 788.074137c-10.414219 0-18.979184-8.467636-18.979184-18.979184s8.467636-18.979184 18.979184-18.979185h489.857618c10.414219 0 18.979184 8.467636 18.979185 18.979185s-8.467636 18.979184-18.979185 18.979184H304.542914z m367.417546-122.537401c-10.414219 0-18.979184-8.467636-18.979184-18.979184 0-10.414219 8.467636-18.979184 18.979184-18.979185h122.440072c10.414219 0 18.979184 8.467636 18.979185 18.979185 0 10.414219-8.467636 18.979184-18.979185 18.979184H671.96046z m-244.977474 0c-10.414219 0-18.979184-8.467636-18.979184-18.979184V279.237335c0-5.061116 1.946583-9.830244 5.547762-13.431423 3.601179-3.601179 8.370307-5.547762 13.431422-5.547762s9.830244 1.946583 13.431423 5.547762c3.601179 3.601179 5.547762 8.370307 5.547762 13.431423v367.417546c0 10.414219-8.467636 18.881855-18.979185 18.881855zM671.96046 543.096664c-10.414219 0-18.979184-8.467636-18.979184-18.979185 0-10.414219 8.467636-18.979184 18.979184-18.979184h122.440072c10.414219 0 18.979184 8.467636 18.979185 18.979184 0 10.414219-8.467636 18.979184-18.979185 18.979185H671.96046z m0-122.440072c-10.414219 0-18.979184-8.467636-18.979184-18.979185 0-10.414219 8.467636-18.979184 18.979184-18.979184h183.660108c10.414219 0 18.979184 8.467636 18.979185 18.979184 0 10.414219-8.467636 18.979184-18.979185 18.979185H671.96046z m0-122.440073c-10.414219 0-18.979184-8.467636-18.979184-18.979184 0-10.414219 8.467636-18.979184 18.979184-18.979185h183.660108c10.414219 0 18.979184 8.467636 18.979185 18.979185 0 10.414219-8.467636 18.979184-18.979185 18.979184H671.96046z" ></path><path d="M847.44492 914.407376H251.498527c-48.956563 0-88.861515-39.807623-88.861515-88.861515V229.599468c0-48.956563 39.807623-88.861515 88.861515-88.861515h298.021861c10.706207 0 19.46583 8.759624 19.46583 19.46583s-8.759624 19.46583-19.46583 19.46583H251.498527c-27.54415 0-49.929855 22.385705-49.929855 49.929855v596.043722c0 27.54415 22.385705 49.929855 49.929855 49.929854h596.043722c27.54415 0 49.929855-22.385705 49.929854-49.929854V508.544815c0-10.706207 8.759624-19.46583 19.465831-19.46583s19.46583 8.759624 19.46583 19.46583v317.098375c-0.097329 48.956563-39.904952 88.764186-88.958844 88.764186z" ></path></symbol><symbol id="icon-link" viewBox="0 0 1024 1024"><path d="M272.6 952.3c-55.4 0-107.3-21.4-146.3-60.4C87.4 853 66 801.1 66 745.7c0-55.4 21.4-107.3 60.4-146.3l134-134c12.5-12.5 32.8-12.5 45.3 0l0 0c12.5 12.5 12.5 32.8 0 45.3l-134 134c-26.8 26.8-41.6 62.7-41.6 101s14.8 74.2 41.6 101 62.7 41.6 101 41.6 74.2-14.8 101-41.6l156.6-156.6c26.8-26.8 41.6-62.7 41.6-101 0-29.4-8.7-57.3-24.8-80.8-8.7-12.7-7.1-29.8 3.8-40.7l0 0c14.2-14.2 37.8-11.9 49.2 4.6 23.4 34.1 36 74.5 36 116.9 0 55.4-21.4 107.3-60.4 146.3L418.8 892C379.9 930.9 328 952.3 272.6 952.3zM687.1 552.3 687.1 552.3c-12.5-12.5-12.5-32.8 0-45.3l134-134c26.8-26.8 41.6-62.7 41.6-101s-14.8-74.2-41.6-101-62.7-41.6-101-41.6-74.2 14.8-101 41.6L462.4 327.6c-26.8 26.8-41.6 62.7-41.6 101 0 29.4 8.7 57.3 24.8 80.8 8.7 12.7 7.1 29.8-3.8 40.7l0 0c-14.2 14.2-37.8 11.9-49.2-4.6-23.4-34.1-36-74.5-36-116.9 0-55.4 21.4-107.3 60.4-146.3L573.7 125.7c38.9-38.9 90.9-60.4 146.3-60.4 55.4 0 107.3 21.4 146.3 60.4 38.9 38.9 60.4 90.9 60.4 146.3s-21.4 107.3-60.4 146.3l-134 134C719.8 564.8 699.6 564.8 687.1 552.3z" ></path></symbol><symbol id="icon-alert" viewBox="0 0 1024 1024"><path d="M940.33909 768.957303l-357.420389-595.785242c-39.767725-66.258053-104.845906-66.258053-144.614655 0L80.88468 768.957303c-39.768749 66.25703-7.730055 120.488165 71.184249 120.488165l717.081819 0C948.069145 889.445468 980.104769 835.214333 940.33909 768.957303zM510.610862 824.682465c-63.828724-0.936325-63.828724 0.933255-63.828724-63.830771 0-62.894446 0-62.894446 63.828724-63.827701 63.827701-0.933255 63.827701 0.933255 63.827701 63.827701C574.438563 825.615721 574.438563 825.615721 510.610862 824.682465zM574.438563 634.129548 446.782138 634.129548 446.782138 314.981834l127.656425 0L574.438563 634.129548z" ></path></symbol><symbol id="icon-alert1" viewBox="0 0 1024 1024"><path d="M0 0h1024v1024H0z" fill="#FFFFFF" fill-opacity="0" ></path><path d="M532.526 116.675l0.2 0.342L956.802 855.01A24.063 24.063 0 0 1 960 867c0 13.123-10.497 23.786-23.526 24.001H87.926a23.861 23.861 0 0 1-11.948-3.208c-11.332-6.555-15.296-21.005-8.971-32.436l0.195-0.346 424.076-737.993a23.962 23.962 0 0 1 8.776-8.805c11.33-6.554 25.781-2.756 32.472 8.463z m-20.524 60.382l-382.67 665.94h765.34l-382.67-665.94zM517.987 688c9.919 0 17.96 8.059 17.96 18v12c0 9.941-8.041 18-17.96 18h-11.974c-9.919 0-17.96-8.059-17.96-18v-12c0-9.941 8.041-18 17.96-18h11.974z m-11.475-272.013l11.974 0.026c9.918 0.023 17.941 8.1 17.92 18.04l-0.42 188c-0.022 9.942-8.08 17.983-18 17.96l-11.973-0.026c-9.919-0.023-17.942-8.1-17.92-18.04l0.42-188c0.021-9.942 8.08-17.983 18-17.96z" fill="#000000" ></path></symbol><symbol id="icon-gitee" viewBox="0 0 1024 1024"><path d="M828.70047781 442.48641182H473.36932405v0.00772492A30.89836137 30.89836137 0 0 0 442.47096268 473.38477319l-0.0308983 77.24590276a30.89836137 30.89836137 0 0 0 30.89836137 30.90608628L689.6578523 581.52903732a30.89836137 30.89836137 0 0 1 30.89836139 30.89836138v15.44918069c0 51.19086008-41.50422404 92.69508343-92.69508346 92.69508344H334.30352449a30.89836137 30.89836137 0 0 1-30.89836138-30.89836138V396.13886977h-0.00772424c0-51.19086008 41.49649912-92.69508343 92.69508345-92.69508346h432.52298485v-0.01544914a30.89836137 30.89836137 0 0 0 30.89836136-30.88291223l0.0695215-77.24590275H859.59883918a30.89836137 30.89836137 0 0 0-30.89836137-30.91381052L396.1234206 164.40116082C268.14240861 164.40116082 164.38571167 268.15785777 164.38571167 396.13886977v432.57705719a30.89836137 30.89836137 0 0 0 30.89836137 30.89836137h455.75082756c115.18909066 0 208.56393792-93.37484793 208.56393858-208.56393792V473.38477319a30.89836137 30.89836137 0 0 0-30.89836137-30.89836137z" fill="#C71D23" ></path></symbol><symbol id="icon-github" viewBox="0 0 1024 1024"><path d="M932 512a408 408 0 0 1-80.4 246.9 412.5 412.5 0 0 1-206.7 151.8 25.2 25.2 0 0 1-21.6-3.9 21.3 21.3 0 0 1-6.6-16.5v-115.2a98.1 98.1 0 0 0-28.5-77.7 390 390 0 0 0 55.8-9.6 204.6 204.6 0 0 0 51.3-21.6 154.5 154.5 0 0 0 44.1-36 172.5 172.5 0 0 0 30-57.6 275.4 275.4 0 0 0 11.4-82.5 158.1 158.1 0 0 0-43.5-112.5 145.2 145.2 0 0 0-4.2-111.6 71.7 71.7 0 0 0-44.1 6 281.7 281.7 0 0 0-50.4 24l-20.7 12.9a390 390 0 0 0-210 0c-6-4.2-13.5-8.7-23.1-14.7A305.7 305.7 0 0 0 338 272a77.7 77.7 0 0 0-47.1-7.5 147 147 0 0 0-3.9 112.5 162.9 162.9 0 0 0-43.2 113.1A270 270 0 0 0 255.2 572a184.2 184.2 0 0 0 30 57.6 142.5 142.5 0 0 0 44.1 36.6 251.1 251.1 0 0 0 51.3 21.6 388.2 388.2 0 0 0 56.1 9.6 86.7 86.7 0 0 0-27 56.4 93 93 0 0 1-24.9 7.8 156.9 156.9 0 0 1-30 2.7A64.8 64.8 0 0 1 316.4 752a102.6 102.6 0 0 1-30-34.2 90 90 0 0 0-26.4-28.5 75.6 75.6 0 0 0-27-13.2h-10.8a39 39 0 0 0-15.9 2.4q-4.5 2.7-2.7 6.3a41.4 41.4 0 0 0 5.1 7.5 51.9 51.9 0 0 0 7.2 6.9l3.9 2.4a73.2 73.2 0 0 1 24 20.7 147.9 147.9 0 0 1 17.1 27.6l5.4 12.6a67.8 67.8 0 0 0 24 33.9 90 90 0 0 0 36.3 15.6 183.9 183.9 0 0 0 37.8 3.9 170.7 170.7 0 0 0 30-2.1l12.6-2.1v78.6a21.6 21.6 0 0 1-7.2 16.5 26.1 26.1 0 0 1-21.9 3.9 410.7 410.7 0 0 1-205.5-152.7A401.1 401.1 0 0 1 92 512a410.1 410.1 0 0 1 56.4-210A415.8 415.8 0 0 1 302 148.4 410.1 410.1 0 0 1 512 92a410.1 410.1 0 0 1 210 56.4A415.8 415.8 0 0 1 875.6 302 409.5 409.5 0 0 1 932 512z" fill="#333333" ></path></symbol><symbol id="icondialog" viewBox="0 0 1024 1024"><path d="M930.133 68.267H93.867C42.667 68.267 0 110.933 0 162.133v699.734c0 51.2 42.667 93.866 93.867 93.866h836.266c51.2 0 93.867-42.666 93.867-93.866V162.133c0-51.2-42.667-93.866-93.867-93.866z m0 51.2s1.707 0 0 0H92.16h837.973z m42.667 742.4c0 23.893-18.773 42.666-42.667 42.666H93.867c-23.894 0-42.667-18.773-42.667-42.666V307.2h921.6v554.667z" ></path><path d="M597.333 484.693H170.667c-13.654 0-25.6-11.946-25.6-25.6s11.946-25.6 25.6-25.6h426.666c13.654 0 25.6 11.947 25.6 25.6s-11.946 25.6-25.6 25.6z m-102.4 146.774H170.667c-13.654 0-25.6-11.947-25.6-25.6s11.946-25.6 25.6-25.6h324.266c13.654 0 25.6 11.946 25.6 25.6s-11.946 25.6-25.6 25.6z m256 145.066H170.667c-13.654 0-25.6-11.946-25.6-25.6s11.946-25.6 25.6-25.6h580.266c13.654 0 25.6 11.947 25.6 25.6s-11.946 25.6-25.6 25.6z" ></path></symbol><symbol id="icon_map" viewBox="0 0 1024 1024"><path d="M995.84 279.04a60.330667 60.330667 0 0 0-58.88-3.413333l-130.56 64a42.666667 42.666667 0 1 0 37.546667 76.8L938.666667 370.346667v436.053333l-276.48 130.56-279.893334-139.093333a60.586667 60.586667 0 0 0-52.906666 0L85.333333 916.48V448l92.16-43.52c21.333333-10.24 30.72-35.84 20.48-57.173333a42.496 42.496 0 0 0-56.32-20.48l-106.666666 50.346666c-21.333333 10.24-34.986667 31.573333-34.986667 54.613334v523.946666c0 21.333333 10.24 40.106667 28.16 51.2 17.92 11.093333 39.253333 11.946667 58.88 3.413334l268.8-130.56 279.893333 137.386666c7.68 5.12 17.066667 6.826667 26.453334 6.826667 8.533333 0 17.92-1.706667 25.6-5.973333l301.226666-141.653334c21.333333-9.386667 34.986667-31.573333 34.986667-54.613333V330.24c0-20.48-10.24-40.106667-28.16-51.2z" fill="#333333" ></path><path d="M512 692.053333c28.16 0 54.613333-14.506667 70.826667-38.4C667.306667 523.093333 768 348.16 768 256c0-140.8-115.2-256-256-256S256 115.2 256 256c0 92.16 100.693333 267.093333 185.173333 397.653333 16.213333 23.893333 42.666667 38.4 70.826667 38.4zM512 85.333333c93.866667 0 170.666667 76.8 170.666667 170.666667 0 52.906667-65.706667 187.733333-169.813334 351.573333C407.04 443.733333 341.333333 309.76 341.333333 256c0-93.866667 76.8-170.666667 170.666667-170.666667z" fill="#333333" ></path></symbol><symbol id="iconbianjiqi" viewBox="0 0 1102 1024"><path d="M1063.382161 945.230951a39.384524 39.384524 0 0 1 0 78.769049H39.384524a39.384524 39.384524 0 0 1 0-78.769049h1023.997637z m0-236.307147a39.384524 39.384524 0 0 1 0 78.769049H39.384524a39.384524 39.384524 0 0 1 0-78.769049h1023.997637z m-787.69049-708.921441a50.412191 50.412191 0 0 1 45.292204 27.33286L551.383343 551.385706H461.35032l-72.703832-157.38056H165.415003L94.207783 551.385706H0L231.974849 28.201683A48.83681 48.83681 0 0 1 275.691671 0.002363z m787.69049 472.614294a39.384524 39.384524 0 0 1 0 78.769049h-315.076196a39.384524 39.384524 0 0 1 0-78.769049h315.076196z m-787.69049-347.450275l-76.405977 190.46356h155.096257L275.691671 125.245151zM1063.382161 236.30951a39.384524 39.384524 0 0 1 0 78.769049h-315.076196a39.384524 39.384524 0 0 1 0-78.769049h315.076196z m0-236.307147a39.384524 39.384524 0 0 1 0 78.769049h-315.076196a39.384524 39.384524 0 0 1 0-78.769049h315.076196z" ></path></symbol><symbol id="icondivider" viewBox="0 0 1024 1024"><path d="M904 560H120c-27.2 0-48-20.8-48-48s20.8-48 48-48h784c27.2 0 48 20.8 48 48s-20.8 48-48 48z" ></path></symbol><symbol id="iconanniu" viewBox="0 0 1024 1024"><path d="M337.408 512c0 23.04 4.608 45.568 13.312 67.072 8.704 20.992 21.504 40.448 37.888 56.832 16.384 16.384 35.328 29.184 56.832 37.888 20.992 8.704 44.032 13.312 67.072 13.312s45.568-4.608 67.072-13.312c20.992-8.704 40.448-21.504 56.832-37.888 16.384-16.384 29.184-35.328 37.888-56.832 8.704-20.992 13.312-44.032 13.312-67.072s-4.608-45.568-13.312-67.072c-8.704-20.992-21.504-40.448-37.888-56.832-16.384-16.384-35.328-29.184-56.832-37.888-20.992-8.704-44.032-13.312-67.072-13.312s-45.568 4.608-67.072 13.312c-20.992 8.704-40.448 21.504-56.832 37.888-16.384 16.384-29.184 35.328-37.888 56.832-8.704 21.504-13.312 44.032-13.312 67.072zM512 201.216c171.008 0 310.784 139.776 310.784 310.784 0 171.008-139.776 310.784-310.784 310.784-171.008 0-310.784-139.776-310.784-310.784 0-171.008 139.776-310.784 310.784-310.784m0-77.312c-213.504 0-388.096 174.592-388.096 388.096 0 213.504 174.592 388.096 388.096 388.096 213.504 0 388.096-174.592 388.096-388.096 0-213.504-174.592-388.096-388.096-388.096z" ></path></symbol><symbol id="icon-button" viewBox="0 0 1024 1024"><path d="M211.98 394.08h104.44c22.43 0 39.94 5.34 52.54 16.02 12.17 10.25 18.26 24.14 18.26 41.65 0 12.81-3.2 23.71-9.61 32.68-6.62 8.54-15.49 14.85-26.59 18.9 15.16 2.99 26.59 9.08 34.28 18.26 7.69 9.19 11.53 21.57 11.53 37.16 0 22.86-7.9 39.73-23.71 50.62-13.46 8.97-32.36 13.46-56.7 13.46H211.98V394.08z m34.92 28.83v68.24h60.23c15.8 0 27.34-2.77 34.6-8.33 7.05-5.77 10.57-14.74 10.57-26.91 0-11.53-3.52-19.86-10.57-24.99-6.84-5.34-18.16-8.01-33.96-8.01H246.9z m0 96.75v74.32h64.71c14.31 0 25.84-2.35 34.6-7.05 10.46-6.19 15.7-15.8 15.7-28.83 0-13.46-4.06-23.28-12.17-29.47-7.9-5.98-20.29-8.97-37.16-8.97H246.9z" fill="#333333" ></path><path d="M316.42 627.82H206.98V389.08h109.44c23.53 0 42.3 5.79 55.77 17.2 13.29 11.19 20.03 26.49 20.03 45.46 0 13.82-3.55 25.79-10.54 35.58l-0.12 0.16c-4.5 5.81-9.99 10.69-16.41 14.6 9.97 3.71 18.01 9.16 23.98 16.29 8.43 10.07 12.7 23.65 12.7 40.37 0 24.49-8.7 42.9-25.87 54.74-14.29 9.53-34.3 14.34-59.54 14.34z m-99.44-10h99.44c23.23 0 41.37-4.24 53.93-12.62 14.43-9.95 21.48-25.16 21.48-46.46 0-14.31-3.49-25.73-10.37-33.95-6.9-8.24-17.47-13.81-31.41-16.56l-17.55-3.47 16.8-6.14c10.12-3.7 18.29-9.48 24.29-17.19 5.72-8.05 8.62-18.04 8.62-29.69 0-16.11-5.39-28.48-16.48-37.82-11.63-9.85-28.22-14.84-49.32-14.84h-99.44v218.74z m94.64-18.83H241.9v-84.32h70.67c18.15 0 31.3 3.26 40.18 9.98 9.4 7.18 14.16 18.43 14.16 33.46 0 14.86-6.11 26.01-18.15 33.14l-0.18 0.1c-9.45 5.07-21.89 7.64-36.96 7.64z m-59.72-10h59.71c13.36 0 24.17-2.15 32.14-6.4 8.85-5.28 13.15-13.28 13.15-24.48 0-11.91-3.34-20.25-10.21-25.5-6.96-5.27-18.45-7.94-34.13-7.94H251.9v64.32z m55.23-92.84H241.9v-78.24h65.87c17.05 0 29.15 2.95 36.97 9.02 8.34 6.1 12.56 15.85 12.56 28.98 0 13.69-4.17 24.04-12.41 30.78l-0.13 0.1c-8.22 6.3-20.53 9.36-37.63 9.36z m-55.23-10h55.23c14.56 0 25.16-2.44 31.5-7.25 5.84-4.81 8.67-12.33 8.67-22.99 0-9.93-2.78-16.78-8.51-20.94l-0.14-0.1c-5.91-4.61-16.3-6.95-30.88-6.95H251.9v58.23zM414.45 394.08h187.41v29.79h-76.25v198.95h-34.6V423.87h-76.57v-29.79z" fill="#333333" ></path><path d="M530.62 627.82h-44.6V428.87h-76.57v-39.79h197.41v39.79h-76.25v198.95z m-34.6-10h24.6V418.87h76.25v-19.79H419.45v19.79h76.57v198.95z" fill="#333333" ></path><path d="M629.42 394.08h35.24l116.93 170.11h1.28V394.08h34.92v228.74h-33.96L665.62 450.78h-1.28v172.04h-34.92V394.08z" fill="#333333" ></path><path d="M822.79 627.82H781.2l-111.87-162.8v162.8h-44.92V389.08h42.87l110.58 160.88V389.08h44.92v238.74z m-36.33-10h26.33V399.08h-24.92v170.11h-8.91l-1.49-2.17-115.44-167.94h-27.61v218.74h24.92V445.78h8.91l118.21 172.04z" fill="#333333" ></path><path d="M884.08 819.68H146c-43.71 0-79.47-35.76-79.47-79.47V258.42c0-43.71 35.76-79.47 79.47-79.47h738.08c43.71 0 79.47 35.76 79.47 79.47V740.2c0 43.72-35.76 79.48-79.47 79.48z m15.4-129.88V308.83c0-36.2-29.61-65.81-65.81-65.81H196.41c-36.2 0-65.81 29.61-65.81 65.81V689.8c0 36.2 29.61 65.81 65.81 65.81h637.26c36.19 0 65.81-29.62 65.81-65.81z" fill="#333333" ></path></symbol><symbol id="icon-button1" viewBox="0 0 1024 1024"><path d="M787.692308 236.307692a78.769231 78.769231 0 0 1 78.76923 78.769231v393.846154a78.769231 78.769231 0 0 1-78.76923 78.769231H236.307692a78.769231 78.769231 0 0 1-78.76923-78.769231V315.076923a78.769231 78.769231 0 0 1 78.76923-78.769231h551.384616z m0 39.384616H236.307692a39.384615 39.384615 0 0 0-39.108923 34.776615L196.923077 315.076923v393.846154a39.384615 39.384615 0 0 0 34.776615 39.108923L236.307692 748.307692h551.384616a39.384615 39.384615 0 0 0 39.108923-34.776615L827.076923 708.923077V315.076923a39.384615 39.384615 0 0 0-34.776615-39.108923L787.692308 275.692308zM349.814154 422.045538c16.777846 0 30.011077 4.017231 39.463384 12.051693 8.743385 7.561846 13.233231 17.723077 13.233231 30.483692 0 9.452308-2.363077 17.486769-6.852923 24.103385-4.489846 6.144-10.870154 10.633846-19.377231 13.942154 11.106462 2.126769 19.377231 6.616615 25.048616 13.469538 5.435077 6.616615 8.270769 15.832615 8.270769 27.175385 0 17.014154-5.907692 29.538462-17.486769 37.572923-9.924923 6.616615-24.103385 9.924923-42.062769 9.924923H272.541538v-168.723693z m211.022769 0v23.63077h-55.296V590.769231h-27.648v-145.092923H422.596923v-23.63077h138.24z m47.734154 0l83.416615 121.698462h0.945231v-121.698462h27.884308V590.769231h-26.939077l-84.361846-123.352616h-0.945231V590.769231h-27.648v-168.723693h27.648z m-261.828923 93.577847H300.189538v52.460307h45.843693c10.397538 0 18.668308-1.654154 24.576-4.962461 7.561846-4.253538 11.342769-10.870154 11.342769-20.322462 0-9.688615-2.835692-16.541538-8.270769-20.795077-5.671385-4.253538-14.651077-6.380308-26.939077-6.380307z m-3.780923-70.892308H300.189538v48.206769h42.299077c11.815385 0 20.086154-2.126769 25.048616-5.907692 4.726154-4.017231 7.325538-10.397538 7.325538-19.140923 0-8.034462-2.599385-13.942154-7.325538-17.486769-5.198769-3.780923-13.233231-5.671385-24.576-5.671385z" fill="#333333" ></path></symbol><symbol id="iconadd" viewBox="0 0 1024 1024"><path d="M511.999488 0.011776C441.242716 0.011776 374.786644 13.374668 312.733671 40.100454A514.701762 514.701762 0 0 0 150.382205 149.512337 522.586381 522.586381 0 0 0 40.61193 312.0174 494.324631 494.324631 0 0 0 0.011264 511.488012c0 70.807971 13.516489 137.315242 40.600666 199.470612a522.586381 522.586381 0 0 0 109.770275 162.505062 521.971995 521.971995 0 0 0 162.300268 109.923872A492.942262 492.942262 0 0 0 511.999488 1023.988224c70.756773 0 137.212844-13.516489 199.265817-40.600666a521.971995 521.971995 0 0 0 162.351466-109.923872 522.586381 522.586381 0 0 0 109.770275-162.505062A494.324631 494.324631 0 0 0 1023.987713 511.488012a494.324631 494.324631 0 0 0-40.600667-199.470612 522.586381 522.586381 0 0 0-109.770275-162.505063 514.701762 514.701762 0 0 0-162.300267-109.411883A498.471735 498.471735 0 0 0 511.999488 0.011776z m0 916.663716a392.387775 392.387775 0 0 1-157.692373-31.743269 414.710462 414.710462 0 0 1-128.509044-86.474812A402.934733 402.934733 0 0 1 107.221598 511.488012c0-55.550722 10.598156-108.029515 31.74327-157.282783a409.078591 409.078591 0 0 1 86.935601-129.174629 410.256164 410.256164 0 0 1 128.509044-87.037998A392.387775 392.387775 0 0 1 511.999488 106.300531c56.216307 0 108.746299 10.598156 157.692373 31.74327 48.894875 21.247511 91.697091 50.174846 128.509045 87.037998a409.078591 409.078591 0 0 1 86.884401 129.174629c21.145114 49.304466 31.74327 101.73206 31.74327 157.282783 0 56.267506-10.598156 109.053492-31.74327 158.306759a402.934733 402.934733 0 0 1-86.9356 128.66264 414.710462 414.710462 0 0 1-128.509044 86.474811 392.387775 392.387775 0 0 1-157.641175 31.74327z" fill="#444444" ></path><path d="M767.9936 562.226045V461.825154h-205.768067V256.005888H461.824642v205.768067H256.005376v100.45209h205.768067V767.994112h100.45209v-205.768067z" fill="#444444" ></path></symbol><symbol id="icon-password" viewBox="0 0 1024 1024"><path d="M142.52800001 827.904A249.6 249.6 0 0 0 543.744 544l309.568-309.376-5.75999999-111.744-111.74400001-5.76-44.8 44.8s58.752 58.752 39.168 78.336-78.208-39.04-78.336-39.168l-39.168 39.168s58.752 58.816 39.16800001 78.336-78.272-39.04-78.27200001-39.04l3.264-3.264-42.432 42.432c0.192 0.32 58.368 58.88 39.168 78.08s-78.33600001-39.168-78.336-39.168l14.336-14.016-83.2 83.2a249.6 249.6 0 0 0-283.776 401.216z m117.43999998-235.008a83.2 83.2 0 1 1 1e-8 117.504 83.2 83.2 0 0 1-1e-8-117.504z" ></path></symbol><symbol id="icon-lock" viewBox="0 0 1024 1024"><path d="M832 464h-68V240c0-70.7-57.3-128-128-128H388c-70.7 0-128 57.3-128 128v224h-68c-17.7 0-32 14.3-32 32v384c0 17.7 14.3 32 32 32h640c17.7 0 32-14.3 32-32V496c0-17.7-14.3-32-32-32zM332 240c0-30.9 25.1-56 56-56h248c30.9 0 56 25.1 56 56v224H332V240z m460 600H232V536h560v304zM484 701v53c0 4.4 3.6 8 8 8h40c4.4 0 8-3.6 8-8v-53a48.01 48.01 0 1 0-56 0z" ></path></symbol><symbol id="icon-html" viewBox="0 0 1024 1024"><path d="M824.4736 536.2176v-404.992c0-44.1344-35.8912-80.0256-80.0768-80.0256H423.8336l-60.16 0.6144-260.4544 259.84v581.12c0 44.1344 35.8912 80.0256 80.0768 80.0256h561.152c44.1344 0 80.0256-35.8912 80.0256-80.0768v-35.8912H764.416v15.9744a40.1408 40.1408 0 0 1-40.192 40.192H203.2128a40.1408 40.1408 0 0 1-40.192-40.192V371.8144h180.4288c44.1344 0 80.0768-35.8912 80.0768-80.0768V111.3088h300.6464c22.0672 0 40.192 17.8176 40.192 40.192v385.024h60.1088v-0.3072zM371.0464 268.6976a43.0592 43.0592 0 0 1-42.9568 43.008H196.1472l174.8992-174.8992v131.8912z" ></path><path d="M340.6848 795.8016v-71.5264h-66.56v71.5264H232.96V625.152h41.0624v64.7168h66.56v-64.7168h41.1648v170.5984h-41.1136z m149.7088-135.6288v135.6288h-41.1136v-135.6288h-48.128v-35.2768h137.728v35.328h-48.4864z m221.7984 135.6288l0.9216-120.8832h-0.6144l-44.4928 120.832h-28.8256l-43.264-120.832h-0.6144l0.9216 120.832h-38.912v-170.496h58.5728l38.912 109.4656h0.9728l37.12-109.5168h59.4944v170.5984h-40.192z m75.4688 0V625.152h41.4208v134.656h65.9456v35.9424h-107.3664z" ></path></symbol><symbol id="icon-time" viewBox="0 0 1024 1024"><path d="M511.283686 862.823134c-197.953468 0-358.916463-161.015184-358.916463-358.865297 0-197.901279 160.962995-358.864274 358.916463-358.864274 197.850114 0 358.813109 160.962995 358.813109 358.864274C870.100888 701.80795 709.133799 862.823134 511.283686 862.823134M511.283686 206.672036c-164.012448 0-297.438273 133.321448-297.438273 297.2858 0 163.961282 133.425825 297.334919 297.438273 297.334919 163.909094 0 297.339012-133.373637 297.339012-297.334919C808.622698 339.997578 675.196873 206.672036 511.283686 206.672036" ></path><path d="M668.589384 534.696931 511.283686 534.696931c-16.972557 0-30.791284-13.770632-30.791284-30.739095L480.492402 313.167512c0-16.968463 13.818727-30.78719 30.791284-30.78719 16.968463 0 30.686906 13.818727 30.686906 30.78719l0 160.051229 126.618792 0c17.020652 0 30.686906 13.770632 30.686906 30.739095S685.610036 534.696931 668.589384 534.696931" ></path></symbol><symbol id="icon-chart1" viewBox="0 0 1024 1024"><path d="M129.723 576.837V768.11c0 35.114 63.758 63.757 63.758 63.757H894.82s64.692-10.398 64.692 18.556c0 28.89-30.76 44.394-30.76 44.394l-771.32-1.057c-92.4 0-91.528-102.237-91.528-102.237V167.515c0-31.008 45.329-36.178 45.329-36.178 28.89 0 18.492 62.95 18.492 62.95v318.788l-0.001 63.762z" ></path><path d="M894.532 309.677l-216.279-111.7-265.54 370.686c-6.732 11.136-20.142 14.234-30.347 7.069L234.369 469.939l-38.789-31.471-2.458-13.025c0-8.909 4.435-17.043 11.487-21.255 7.053-4.212 15.602-3.873 22.44 0.968l160.874 116.88 264.845-369.571c6.411-10.797 19.287-13.993 29.332-7.795l245.343 129.952c6.84 4.31 11.06 12.347 11.06 21.062 0 0 0 13.267-13.731 19.319s-30.24-5.326-30.24-5.326zM192 604.685V771h748V494.584L685.198 422.49l-295.3 251.384L192 604.685z" ></path></symbol><symbol id="icon-timerange" viewBox="0 0 1024 1024"><path d="M211.541333 541.397333l86.144-0.725333 0.213334 29.653333-86.144 0.682667-0.213334-29.610667z m310.229334-29.482666a51.626667 51.626667 0 0 1 22.698666 5.034666 519.466667 519.466667 0 0 1 89.088-86.741333l24.704 23.168a495.786667 495.786667 0 0 1-85.290666 99.669333 51.882667 51.882667 0 0 1-50.389334 62.677334 51.925333 51.925333 0 0 1-43.349333-81.152 887.338667 887.338667 0 0 1-99.242667-166.442667l25.941334-14.506667a1039.616 1039.616 0 0 1 100.821333 160.64c4.693333-1.493333 9.770667-2.304 15.018667-2.346666z m-76.544-282.410667l0.554666 88.704 243.712-142.677333L444.117333 35.754667l0.469334 90.965333a432.512 432.512 0 0 0-241.408 124.117333 432.298667 432.298667 0 0 0-124.544 307.413334c0.938667 115.370667 47.232 224.554667 129.408 305.450666s192.128 125.397333 307.413333 124.501334a431.957333 431.957333 0 0 0 305.450667-129.322667 434.005333 434.005333 0 0 0 104.789333-174.250667l4.864-15.658666-97.322667-27.989334-4.736 14.762667a331.946667 331.946667 0 0 1-79.786666 132.096 331.306667 331.306667 0 0 1-234.026667 99.157333 331.52 331.52 0 0 1-235.562667-95.402666 331.349333 331.349333 0 0 1-99.157333-234.069334 330.837333 330.837333 0 0 1 95.445333-235.52 330.666667 330.666667 0 0 1 169.813334-92.501333z m394.709333 272.981333a321.92 321.92 0 0 0-16.213333-62.250666l-5.461334-14.848 94.677334-36.181334 5.632 15.104c10.794667 29.226667 18.389333 59.52 22.656 90.325334l2.474666 17.408-101.461333 4.522666-2.304-14.08z m-0.938667 110.549334c3.541333-20.096 5.248-40.405333 5.034667-60.8l-0.085333-6.016-0.341334-15.701334 101.12-4.437333 0.512 16.256c0.085333 3.029333 0.085333 6.101333 0.128 9.130667 0.213333 29.098667-2.474667 58.197333-8.021333 86.784l-3.328 17.152-97.578667-28.16 2.56-14.208z m-33.152-212.992a331.733333 331.733333 0 0 0-31.488-48.810667l-9.770666-12.501333 79.232-63.061334 9.941333 12.714667c17.578667 22.442667 32.853333 46.592 45.653333 72.064l7.936 15.829333-94.933333 36.352-6.570667-12.586666zM755.2 328.32l-10.282667-10.112a331.818667 331.818667 0 0 0-48.512-39.552l-14.378666-9.6 62.762666-80.128 12.373334 8.533333c20.992 14.421333 40.704 30.677333 58.88 48.512 2.090667 2.133333 4.224 4.224 6.272 6.4l12.416 12.672L755.2 328.32z m-240.64 521.216l-0.725333-86.101333 29.653333-0.256 0.682667 86.101333-29.610667 0.256z m216.832-87.68l-61.354667-60.416 20.778667-21.162667 61.354667 60.501334-20.778667 21.077333z m-432.170667-3.626667l60.458667-61.397333 21.162667 20.821333-60.416 61.354667-21.205334-20.778667z m3.669334-432.170666l61.354666 60.458666-20.736 21.12-61.397333-60.416 20.778667-21.162666z m432.170666 3.712l-21.162666-20.821334-60.416 61.354667 21.12 20.864 60.458666-61.397333z m87.637334 216.832l-86.144 0.682666-0.298667-29.653333 86.229333-0.682667 0.213334 29.653334z" ></path></symbol><symbol id="icon-checkbox" viewBox="0 0 1024 1024"><path d="M837.9973144531249 90.125H186.00268554687506C133.26831054687506 90.125 90.125 133.26831054687506 90.125 186.00268554687506V837.9973144531249c0 52.734375 43.143310546875 95.877685546875 95.877685546875 95.877685546875h651.9946289062499c52.734375 0 95.877685546875-43.143310546875 95.877685546875-95.877685546875V186.00268554687506C933.875 133.26831054687506 890.7316894531249 90.125 837.9973144531249 90.125z m38.35189819335938 747.8714904785157c0 20.71060180664063-17.647064208984375 38.34613037109375-38.35272216796874 38.34613037109375H186.00350952148438c-20.711425781249996 0-38.34613037109375-17.63552856445312-38.34613037109375-38.34613037109375V186.00268554687506c0-20.704833984375 17.634704589843754-38.34613037109375 38.34613037109375-38.34613037109375h651.9929809570312c20.705657958984375 0 38.35272216796874 17.64129638671875 38.35272216796874 38.34613037109375V837.9973144531249zM752.6846313476562 291.9674682617188L394.40234375 665.5369567871094 269.36090087890625 535.1421508789062c-11.378265380859373-11.871002197265625-29.824584960937496-11.871002197265625-41.2020263671875 0-11.384857177734375 11.865234375-11.384857177734375 31.095153808593746 0 42.96697998046875l145.64163208007812 151.8914794921875c5.692016601562501 5.9326171875 13.149810791015623 8.89892578125 20.60101318359375 8.89892578125 7.463562011718751 0 14.914764404296875-2.96630859375 20.60101318359375-8.89892578125l378.8841247558594-395.0587463378906c11.384857177734375-11.871002197265625 11.384857177734375-31.10256958007813 0-42.974395751953125-11.37744140625-11.871002197265625-29.82376098632812-11.871002197265625-41.2020263671875 0z" ></path></symbol><symbol id="icon-date" viewBox="0 0 1024 1024"><path d="M824 200h-52v-52c0-31.2-26-52-52-52h-52c-31.2 0-52 26-52 52v52H408v-52c0-31.2-26-52-52-52h-52c-26 0-52 26-52 52v52h-52c-57.2 0-104 46.8-104 104v520c0 57.2 46.8 104 104 104h624c57.2 0 104-46.8 104-104V304c0-57.2-46.8-104-104-104z m-156-26c0-15.6 10.4-26 26-26s26 10.4 26 26v26h-52v-26z m-364 0c0-15.6 10.4-26 26-26s26 10.4 26 26v26h-52v-26z m-104 78h624c26 0 52 26 52 52v52H148v-52c0-26 26-52 52-52z m624 624H200c-26 0-52-26-52-52V408h728v416c0 26-26 52-52 52z" ></path><path d="M330 564H226c-15.6 0-26 10.4-26 26s10.4 26 26 26h104c15.6 0 26-10.4 26-26s-10.4-26-26-26zM454.8 616h104c15.6 0 26-10.4 26-26s-10.4-26-26-26h-104c-15.6 0-26 10.4-26 26s10.4 26 26 26zM798 564H694c-15.6 0-26 10.4-26 26s10.4 26 26 26h104c15.6 0 26-10.4 26-26s-10.4-26-26-26zM330 720H226c-15.6 0-26 10.4-26 26s10.4 26 26 26h104c15.6 0 26-10.4 26-26s-10.4-26-26-26zM564 720H460c-15.6 0-26 10.4-26 26s10.4 26 26 26h104c15.6 0 26-10.4 26-26s-10.4-26-26-26zM798 720H694c-15.6 0-26 10.4-26 26s10.4 26 26 26h104c15.6 0 26-10.4 26-26s-10.4-26-26-26z" ></path></symbol><symbol id="icon-setting" viewBox="0 0 1024 1024"><path d="M213.333333 298.666667a85.333333 85.333333 0 0 0 80.64-58.666667c0-2.133333 1.493333-4.053333 1.92-6.186667s1.066667-4.053333 1.28-5.973333A81.493333 81.493333 0 0 0 298.666667 213.333333a81.493333 81.493333 0 0 0-1.493334-14.506666c0-1.92 0-3.84-1.28-5.973334s-1.28-4.053333-1.92-6.186666a98.133333 98.133333 0 0 0-7.04-16A85.333333 85.333333 0 1 0 213.333333 298.666667zM853.333333 256a42.666667 42.666667 0 0 0 0-85.333333H333.866667a125.653333 125.653333 0 0 1 0 85.333333zM810.666667 725.333333a85.333333 85.333333 0 0 0-73.6 42.666667 98.133333 98.133333 0 0 0-7.04 16c0 2.133333-1.493333 4.053333-1.92 6.186667s-1.066667 4.053333-1.28 5.973333a71.253333 71.253333 0 0 0 0 29.013333c0 1.92 0 3.84 1.28 5.973334s1.28 4.053333 1.92 6.186666A85.333333 85.333333 0 1 0 810.666667 725.333333zM170.666667 768a42.666667 42.666667 0 0 0 0 85.333333h519.466666a125.653333 125.653333 0 0 1 0-85.333333zM592.64 485.333333a98.133333 98.133333 0 0 0-7.04-16 85.333333 85.333333 0 0 0-147.2 0 98.133333 98.133333 0 0 0-7.04 16c0 2.133333-1.493333 4.053333-1.92 6.186667s-1.066667 4.053333-1.28 5.973333a71.253333 71.253333 0 0 0 0 29.013334c0 1.92 0 3.84 1.28 5.973333s1.28 4.053333 1.92 6.186667a85.333333 85.333333 0 0 0 161.28 0c0-2.133333 1.493333-4.053333 1.92-6.186667s1.066667-4.053333 1.28-5.973333a71.253333 71.253333 0 0 0 0-29.013334c0-1.92 0-3.84-1.28-5.973333s-1.28-4.053333-1.92-6.186667zM170.666667 554.666667h220.8a125.653333 125.653333 0 0 1 0-85.333334H170.666667a42.666667 42.666667 0 0 0 0 85.333334zM853.333333 469.333333H632.533333a125.653333 125.653333 0 0 1 0 85.333334H853.333333a42.666667 42.666667 0 0 0 0-85.333334z" ></path></symbol><symbol id="icon-slider" viewBox="0 0 1024 1024"><path d="M256 512c6.4-54.4 54.4-96 112-96s102.4 41.6 112 96h480v32H480c-6.4 54.4-54.4 96-112 96S265.6 598.4 256 544H64v-32h192z m112 96c44.8 0 80-35.2 80-80S412.8 448 368 448 288 483.2 288 528s35.2 80 80 80z" ></path></symbol><symbol id="icon-table" viewBox="0 0 1024 1024"><path d="M57.6 132.48v785.92h908.8V132.48z m844.16 64v203.52H121.6V196.48zM397.44 627.2V464h220.16V627.2z m220.8 64v163.2H397.44V691.2zM121.6 464h211.2V627.2H121.6z m560 0h220.8V627.2h-220.8zM121.6 691.2h211.2v163.2H121.6z m560 163.2V691.2h220.8v163.2z" ></path></symbol><symbol id="icon-list" viewBox="0 0 1024 1024"><path d="M287.957333 192.426667h-64C206.314667 192.426667 192 206.72 192 224.341333v63.914667c0 17.621333 14.293333 31.914667 31.957333 31.914667h64c17.642667 0 31.957333-14.293333 31.957334-31.914667v-63.914667c0-17.621333-14.293333-31.914667-31.957334-31.914666z m0 255.573333h-64C206.314667 448 192 462.293333 192 479.914667v63.914666c0 17.621333 14.293333 31.914667 31.957333 31.914667h64c17.642667 0 31.957333-14.293333 31.957334-31.914667v-63.914666c0-17.621333-14.293333-31.914667-31.957334-31.914667z m0 255.573333h-64c-17.642667 0-31.957333 14.293333-31.957333 31.914667v63.914667c0 17.621333 14.293333 31.914667 31.957333 31.914666h64c17.642667 0 31.957333-14.293333 31.957334-31.914666v-63.914667c0-17.621333-14.293333-31.914667-31.957334-31.914667z m127.914667-415.317333h383.829333a31.936 31.936 0 1 0 0-63.829333H415.872a31.936 31.936 0 1 0 0 63.829333z m383.829333 191.658667H415.872a31.936 31.936 0 1 0 0 63.829333h383.829333a31.936 31.936 0 1 0 0-63.829333z m0 255.573333H415.872a31.936 31.936 0 1 0 0 63.829333h383.829333a31.936 31.936 0 1 0 0-63.829333z" ></path></symbol><symbol id="icon-input" viewBox="0 0 1024 1024"><path d="M118.784 727.04h778.24V296.96h-778.24v430.08zM77.824 256h860.16v512H77.824V256zM194.56 409.6v204.8c0 12.288 8.192 20.48 20.48 20.48s20.48-8.192 20.48-20.48V409.6c0-12.288-8.192-20.48-20.48-20.48s-20.48 8.192-20.48 20.48z" ></path></symbol><symbol id="icon-switch" viewBox="0 0 1024 1024"><path d="M355.80067825 749.80525208h312.26500512c131.28464699 0 237.71100998-106.42713547 237.71100997-237.71178246S799.34955788 274.38245964 668.06568337 274.38245964H355.80067825c-131.28387451 0-237.71100998 106.42636299-237.71100998 237.71100998s106.42713547 237.71178246 237.71100998 237.71178246z m-0.26959419-452.93987275c119.13900376 0 215.72788239 96.58347129 215.72788239 215.72788239S474.66931533 728.3211441 355.53108406 728.3211441c-119.14672852 0-215.72865486-96.58501626-215.72865486-215.72788238 0-119.14518356 96.58269882-215.72788239 215.72865486-215.72788239z" ></path></symbol><symbol id="icon-rate" viewBox="0 0 1024 1024"><path d="M512 127.5c-21.5 0-41.1 12.5-50.2 32.1l-86.9 186.3L175 376.6c-20.5 3.2-37.6 17.6-44.2 37.5-6.6 19.9-1.6 41.7 12.9 56.6l146.4 151.2-34 209.6c-3.4 21.1 5.4 42.3 22.8 54.7 9.3 6.6 20.5 10.2 31.9 10.2 9.4 0 18.6-2.4 26.8-7L512 795.6l174.3 93.8c8.4 4.6 17.6 7 26.8 7 11.2 0 22.4-3.5 32-10.2 17.3-12.3 26.2-33.5 22.7-54.7l-34-209.6 146.5-151.1c14.5-14.9 19.5-36.8 12.9-56.7-6.6-19.8-23.7-34.3-44.2-37.5L649.1 346l-86.9-186.4c-9.1-19.6-28.7-32.1-50.2-32.1z m0.5 412l102-143.8-102 143.8 167.1 65.2-167.1-65.2-0.6 197 0.6-197-168.2 65.2 168.2-65.2-103.1-143.8 103.1 143.8z" ></path></symbol><symbol id="icon-att" viewBox="0 0 1024 1024"><path d="M672.1 64.2c25.7 0 51.4 6.4 70.7 12.9C820 109.2 865 180 865 263.6c0 51.4-19.3 102.9-57.9 141.5L447 771.6c-12.9 12.9-25.7 19.3-38.6 25.7-12.9 6.4-25.7 6.4-45 6.4-12.9 0-32.2 0-45-6.4-12.9-6.4-25.7-12.9-32.2-25.7-12.9-12.9-19.3-25.7-25.7-38.6-6.4-12.9-6.4-32.1-6.4-45 0-32.2 12.9-64.3 32.2-83.6l328-340.8c6.4-6.4 19.3-12.9 25.7-12.9 12.9 0 25.7 6.4 32.2 12.9 6.4 6.4 12.9 19.3 12.9 25.7-6.4 12.9-6.4 19.3-12.9 32.2L337.7 655.8c-6.4 6.4-12.9 19.3-12.9 32.2 0 19.3 19.3 38.6 38.6 38.6 12.9 0 19.3-6.4 25.7-12.9l360.1-366.5c25.7-25.7 32.1-51.4 32.1-83.6 0-32.2-12.9-57.9-32.1-83.6-19.3-25.7-45-38.6-77.2-38.6s-64.3 12.9-83.6 38.6l-360 366.5c-19.3 19.3-32.2 38.6-45 64.3-19.3 45-19.3 102.9 0 147.9 12.9 25.7 25.7 45 45 64.3 38.6 38.6 83.6 57.9 135 57.9 51.4 0 102.9-19.3 135-57.9L865 462.9c6.4-12.9 12.9-12.9 25.7-12.9 12.9 0 19.3 6.4 25.7 12.9 6.4 6.4 12.9 12.9 12.9 25.7s-6.4 19.3-12.9 25.7L556.3 880.9c-25.7 25.7-57.9 45-90 64.3-32.2 12.9-64.3 19.3-102.9 19.3-38.6 0-70.7-6.4-102.9-19.3s-64.3-32.2-90-64.3c-25.7-25.7-45-57.9-57.9-90-12.8-32.2-19.2-70.8-19.2-102.9 0-38.6 6.4-70.7 19.3-109.3 12.9-32.2 32.2-64.3 57.9-90l360.1-366.5c38.5-38.7 89.9-58 141.4-58z m0 0" ></path></symbol><symbol id="icon-doc" viewBox="0 0 1024 1024"><path d="M857.6 219.733333c-6.4-6.4-12.8-12.8-19.2-17.066666-19.2-19.2-40.533333-36.266667-59.733333-55.466667l-4.266667-4.266667c-25.6-23.466667-46.933333-42.666667-61.866667-55.466666-8.533333-8.533333-17.066667-12.8-21.333333-17.066667-2.133333-2.133333-6.4-4.266667-8.533333-6.4-2.133333 0-6.4-2.133333-10.666667-2.133333-12.8 0-23.466667 10.666667-23.466667 23.466666v202.666667h202.666667l-23.466667-23.466667V938.666667l23.466667-23.466667H264.533333c-38.4 0-68.266667-29.866667-68.266666-66.133333V85.333333l-21.333334 21.333334h405.333334c12.8 0 23.466667-10.666667 23.466666-23.466667s-10.666667-23.466667-23.466666-23.466667h-426.666667v787.2c0 61.866667 51.2 113.066667 113.066667 113.066667H874.666667V243.2h-202.666667l23.466667 23.466667V85.333333c0 12.8-8.533333 21.333333-21.333334 21.333334-2.133333 0-6.4 0-8.533333-2.133334l2.133333 2.133334c4.266667 2.133333 10.666667 8.533333 19.2 14.933333 14.933333 12.8 36.266667 32 61.866667 53.333333l4.266667 4.266667c19.2 17.066667 38.4 36.266667 59.733333 53.333333 6.4 6.4 12.8 12.8 19.2 17.066667l6.4 6.4c8.533333 8.533333 23.466667 8.533333 32 0 8.533333-8.533333 8.533333-23.466667 0-32-6.4 2.133333-12.8-4.266667-12.8-4.266667z" ></path><path d="M151.466667 467.2H61.866667v381.866667h900.266666V467.2h-810.666666z" ></path></symbol><symbol id="icon-editor" viewBox="0 0 1024 1024"><path d="M218.316 307.727h87.886v205.06h-29.297v29.295h117.179v-29.294H364.79V307.727h87.882v29.293h29.294v-87.882H189.022v87.882h29.294v-29.293z m322.242 58.59h292.945v58.588H540.558v-58.588z m0 117.177h292.945v58.588H540.558v-58.588z m-351.536 117.18h644.481v58.588h-644.48v-58.587z m0 117.176h644.481v58.588h-644.48V717.85z m351.536-468.713h292.945v58.589H540.558v-58.589z m420.923 713.13H61.045V63.309h900.436v898.958z m-864.62-35.816h828.804V99.125H96.861V926.45z" ></path></symbol><symbol id="icon-textarea" viewBox="0 0 1024 1024"><path d="M118.784 778.24h778.24V245.76h-778.24v532.48zM77.824 204.8h860.16v614.4H77.824V204.8z m778.24 409.6l-122.88 122.88h122.88V614.4z m-661.504-256v204.8c0 12.288 8.192 20.48 20.48 20.48s20.48-8.192 20.48-20.48V358.4c0-12.288-8.192-20.48-20.48-20.48s-20.48 8.192-20.48 20.48z" ></path></symbol><symbol id="icon-location" viewBox="0 0 1024 1024"><path d="M512.09668625 332.11341781a99.58288406 99.58288406 0 1 1-70.78783313 29.39494782A99.58288406 99.58288406 0 0 1 512.09668625 332.11341781m0-59.98968937a160.17247031 160.17247031 0 1 0 113.38051313 46.79195812A158.97267656 158.97267656 0 0 0 512.09668625 272.12372844z" ></path><path d="M786.84946344 148.54496844a382.13432062 382.13432062 0 0 0-549.50555344 0 404.33050594 404.33050594 0 0 0 0 562.10338875L512.09668625 992l274.75277719-281.35164281a404.33050594 404.33050594 0 0 0 0-562.10338875z m-41.39288532 522.51019406l-233.35989187 239.95875656-233.35989094-239.95875656a342.54112594 342.54112594 0 0 1 0-476.91802969 325.14411562 325.14411562 0 0 1 466.71978282 0 342.54112594 342.54112594 0 0 1 0 476.91802969z" ></path></symbol><symbol id="icon-col" viewBox="0 0 1024 1024"><path d="M170.666667 128a21.333333 21.333333 0 0 1 21.333333 21.333333v725.333334a21.333333 21.333333 0 0 1-21.333333 21.333333H128a21.333333 21.333333 0 0 1-21.333333-21.333333V149.333333a21.333333 21.333333 0 0 1 21.333333-21.333333h42.666667z m234.666666 0a21.333333 21.333333 0 0 1 21.333334 21.333333v725.333334a21.333333 21.333333 0 0 1-21.333334 21.333333h-42.666666a21.333333 21.333333 0 0 1-21.333334-21.333333V149.333333a21.333333 21.333333 0 0 1 21.333334-21.333333h42.666666z m234.666667 0a21.333333 21.333333 0 0 1 21.333333 21.333333v725.333334a21.333333 21.333333 0 0 1-21.333333 21.333333h-42.666667a21.333333 21.333333 0 0 1-21.333333-21.333333V149.333333a21.333333 21.333333 0 0 1 21.333333-21.333333h42.666667z m234.666667 0a21.333333 21.333333 0 0 1 21.333333 21.333333v725.333334a21.333333 21.333333 0 0 1-21.333333 21.333333h-42.666667a21.333333 21.333333 0 0 1-21.333333-21.333333V149.333333a21.333333 21.333333 0 0 1 21.333333-21.333333h42.666667z" ></path></symbol><symbol id="icon-divider" viewBox="0 0 1088 1024"><path d="M1009.92 723.072l11.072 15.616-30.208 21.504-11.136-15.68 30.208-21.44zM913.28 599.68l9.6 16.64-166.208 96-9.6-16.64 166.272-96z m-138.624 0l9.6 16.64-166.272 96-9.6-16.64 166.272-96z m-138.624 0l9.6 16.64-166.272 96-9.6-16.64 166.272-96z m-138.624 0l9.6 16.64-166.272 96-9.6-16.64 166.272-96z m-138.688 0l9.6 16.64-166.272 96-9.6-16.64 166.272-96zM218.24 586.56l8.32 17.28-44.608 21.504-8.32-17.28 44.608-21.504z m832.32-109.632v32h-1024v-32h1024z m-88.192-86.144l8.32 17.28-44.544 21.504-8.32-17.28 44.544-21.504zM320.384 311.68l9.6 16.64-166.336 96-9.6-16.64 166.336-96z m138.624 0l9.6 16.64-166.272 96-9.6-16.64 166.272-96z m138.624 0l9.6 16.64-166.272 96-9.6-16.64 166.272-96z m138.688 0l9.6 16.64-166.272 96-9.6-16.64 166.272-96z m138.624 0l9.6 16.64-166.272 96-9.6-16.64 166.272-96z m-719.744 0.512l11.136 15.616-30.208 21.504-11.136-15.68 30.208-21.44z" ></path></symbol><symbol id="icon-daterange" viewBox="0 0 1024 1024"><path d="M775.7 159.65H255.95c-53.1 0-96.3 43.2-96.3 96.3v516.15c0 53.1 43.2 96.3 96.3 96.3h520.2c53.1 0 96.3-43.2 96.3-96.3V255.95c-0.45-52.65-43.65-96.3-96.75-96.3z m-18 466.2L638 741.95c-11.7 11.25-31.05 3.15-31.05-13.05v-67.5H424.7v67.5c0 16.2-19.35 24.3-31.05 13.05l-119.7-116.1c-7.2-7.2-7.2-19.35 0-26.1l119.7-116.1c11.7-11.25 31.05-3.15 31.05 13.05v67.5h182.25v-67.5c0-16.2 19.35-24.3 31.05-13.05l119.7 116.1c7.2 6.75 7.2 18.9 0 26.1z m45-320.85c0 33.75-27.45 61.2-61.2 61.2H300.95c-33.75 0-61.2-27.45-61.2-61.2v-1.8c0-33.75 27.45-61.2 61.2-61.2H741.5c33.75 0 61.2 27.45 61.2 61.2v1.8z" ></path></symbol><symbol id="icon-select" viewBox="0 0 1024 1024"><path d="M514.28900146 126.70288086c-211.6774292 0-383.26025391 171.58200073-383.2602539 383.26025391S302.61157227 893.24728393 514.28900146 893.24728393s383.28414917-171.60754394 383.28414917-383.28414916S725.96560669 126.70288086 514.28900146 126.70288086z m0 721.89404297c-187.02493286 0-338.63378906-151.61050415-338.63378906-338.63378906S327.26489258 171.3293457 514.28900146 171.3293457 852.92279052 322.93902588 852.92279052 509.96313477 701.31228638 848.59692383 514.28900146 848.59692383z" ></path><path d="M686.09378162 477.35971851l-154.36416725 168.80000472a24.29205196 24.29205196 0 0 1-18.24720414 8.25668802 24.29205196 24.29205196 0 0 1-18.24720405-8.25668802l-154.36353075-168.8000048c-7.53616916-7.9594421-9.86512545-19.55966871-5.97037725-29.80605811s13.2952282-17.4006582 24.21758138-18.37450426l308.60103432 0c10.96499877 0.9318371 20.40621473 8.04409676 24.3015994 18.33185875 3.93739376 10.28839847 1.60843732 21.84661591-5.92709511 29.84870362z" ></path></symbol><symbol id="icon-radio" viewBox="0 0 1024 1024"><path d="M512 136.99999971c-207.10781279 0-375.00000029 167.89453154-375.00000029 375.00000029s167.8921875 375.00000029 375.00000029 375.00000029c207.10546875 0 375.00000029-167.89453154 375.00000029-375.00000029S719.10546875 136.99999971 512 136.99999971zM512 849.5c-186.3984375 0-337.5-151.10624971-337.5-337.5 0-186.39609346 151.1015625-337.5 337.5-337.5 186.39375029 0 337.5 151.10390654 337.5 337.5C849.5 698.39375029 698.39375029 849.5 512 849.5z" ></path><path d="M512 512m-206.25000029 0a77.34375 77.34375 0 1 0 412.49999971 0 77.34375 77.34375 0 1 0-412.49999971 0Z" ></path></symbol><symbol id="icon-chart" viewBox="0 0 1024 1024"><path d="M192 832h704v64H128V128h64v704z m427.69-257.984l-130.56-130.56-178.218 178.219-45.227-45.248 223.467-223.488 128.49 128.49 206.465-225.706 47.232 43.2L619.69 574.016z" ></path></symbol><symbol id="icon-inputNumber" viewBox="0 0 1024 1024"><path d="M790.961231 567.808c33.476923 0 55.808 22.291692 55.808 55.768615v167.384616c0 33.476923-22.331077 55.808-55.808 55.808H233.038769c-33.476923 0-55.808-22.331077-55.808-55.808v-167.384616c0-33.476923 22.331077-55.768615 55.808-55.768615z m0 33.476923H233.038769c-11.185231 0-22.331077 11.145846-22.331077 22.291692v167.384616c0 11.185231 11.145846 22.331077 22.331077 22.331077h557.922462c11.185231 0 22.331077-11.145846 22.331077-22.331077v-167.384616c0-11.145846-11.145846-22.291692-22.331077-22.291692z m-111.576616 22.291692v66.953847h66.953847v33.476923h-66.953847v66.953846h-33.476923v-66.953846h-66.953846v-33.476923h66.953846v-66.953847h33.476923zM790.961231 177.230769c33.476923 0 55.808 22.331077 55.808 55.808v167.384616c0 33.476923-22.331077 55.768615-55.808 55.768615H233.038769c-33.476923 0-55.808-22.291692-55.808-55.768615v-167.384616c0-33.476923 22.331077-55.808 55.808-55.808z m0 33.476923H233.038769c-11.185231 0-22.331077 11.145846-22.331077 22.331077v167.384616c0 11.145846 11.145846 22.291692 22.331077 22.291692h557.922462c11.185231 0 22.331077-11.145846 22.331077-22.291692v-167.384616c0-11.185231-11.145846-22.331077-22.331077-22.331077zM447.015385 299.992615v33.476923H279.630769v-33.476923h167.384616z" ></path></symbol><symbol id="icon-tab" viewBox="0 0 1024 1024"><path d="M921.6 921.6H102.4c-56 0-102.4-46.4-102.4-102.4V204.8c0-56 46.4-102.4 102.4-102.4h819.2c56 0 102.4 46.4 102.4 102.4v614.4c0 56-46.4 102.4-102.4 102.4z m-768-716.8c-28.8 0-51.2 22.4-51.2 51.2v563.2h819.2V409.6H512c-28.8 0-51.2-22.4-51.2-51.2V256c0-28.8-22.4-51.2-51.2-51.2h-256z" ></path></symbol></svg>',o=(o=document.getElementsByTagName("script"))[o.length-1].getAttribute("data-injectcss"),i=function(h,c){c.parentNode.insertBefore(h,c)};if(o&&!h.__iconfont__svg__cssinject__){h.__iconfont__svg__cssinject__=!0;try{document.write("<style>.svgfont {display: inline-block;width: 1em;height: 1em;fill: currentColor;vertical-align: -0.1em;font-size:16px;}</style>")}catch(h){console&&console.log(h)}}function m(){t||(t=!0,l())}function s(){try{v.documentElement.doScroll("left")}catch(h){return void setTimeout(s,50)}m()}c=function(){var h,c;(c=document.createElement("div")).innerHTML=z,z=null,(h=c.getElementsByTagName("svg")[0])&&(h.setAttribute("aria-hidden","true"),h.style.position="absolute",h.style.width=0,h.style.height=0,h.style.overflow="hidden",c=h,(h=document.body).firstChild?i(c,h.firstChild):h.appendChild(c))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(c,0):(a=function(){document.removeEventListener("DOMContentLoaded",a,!1),c()},document.addEventListener("DOMContentLoaded",a,!1)):document.attachEvent&&(l=c,v=h.document,t=!1,s(),v.onreadystatechange=function(){"complete"==v.readyState&&(v.onreadystatechange=null,m())})}(window);
\ No newline at end of file
{
"id": "1782818",
"name": "form-designer",
"font_family": "iconfont",
"css_prefix_text": "icon",
"description": "",
"glyphs": [
{
"icon_id": "4766919",
"name": "table",
"font_class": "-table_layout",
"unicode": "e7de",
"unicode_decimal": 59358
},
{
"icon_id": "11179893",
"name": "拆分行",
"font_class": "-chaifenhang",
"unicode": "e60a",
"unicode_decimal": 58890
},
{
"icon_id": "11179898",
"name": "拆分列",
"font_class": "-chaifenlie",
"unicode": "e60b",
"unicode_decimal": 58891
},
{
"icon_id": "12819536",
"name": "拆分",
"font_class": "-chaifen",
"unicode": "e60d",
"unicode_decimal": 58893
},
{
"icon_id": "7040012",
"name": "行追加",
"font_class": "-zhuijiahang",
"unicode": "e6ce",
"unicode_decimal": 59086
},
{
"icon_id": "7040014",
"name": "列追加",
"font_class": "-zhuijialie",
"unicode": "e6cf",
"unicode_decimal": 59087
},
{
"icon_id": "10868107",
"name": "插入行",
"font_class": "-charuhang",
"unicode": "e8a2",
"unicode_decimal": 59554
},
{
"icon_id": "10868232",
"name": "插入列",
"font_class": "-charulie",
"unicode": "e8a4",
"unicode_decimal": 59556
},
{
"icon_id": "19324946",
"name": "上下合并",
"font_class": "-shangxiahebing",
"unicode": "e66a",
"unicode_decimal": 58986
},
{
"icon_id": "19324950",
"name": "左右合并",
"font_class": "-zuoyouhebing",
"unicode": "e66b",
"unicode_decimal": 58987
},
{
"icon_id": "19478268",
"name": "treeselect",
"font_class": "-treeselect",
"unicode": "e609",
"unicode_decimal": 58889
},
{
"icon_id": "6801615",
"name": "Barcode",
"font_class": "-barcode2",
"unicode": "e66e",
"unicode_decimal": 58990
},
{
"icon_id": "8924414",
"name": "bar-code",
"font_class": "-barcode",
"unicode": "e612",
"unicode_decimal": 58898
},
{
"icon_id": "16383562",
"name": "Dialog",
"font_class": "-dialog",
"unicode": "e692",
"unicode_decimal": 59026
},
{
"icon_id": "17412502",
"name": "Organization Chart",
"font_class": "-address",
"unicode": "e6b5",
"unicode_decimal": 59061
},
{
"icon_id": "16768231",
"name": "级联",
"font_class": "-cascader",
"unicode": "e697",
"unicode_decimal": 59031
},
{
"icon_id": "7213053",
"name": "Color picker",
"font_class": "-colorpicker",
"unicode": "e666",
"unicode_decimal": 58982
},
{
"icon_id": "14463272",
"name": "省市区",
"font_class": "-shengshiqu",
"unicode": "e75f",
"unicode_decimal": 59231
},
{
"icon_id": "3385558",
"name": "文本",
"font_class": "-text",
"unicode": "e6fb",
"unicode_decimal": 59131
},
{
"icon_id": "371393",
"name": "link",
"font_class": "-link",
"unicode": "e8fb",
"unicode_decimal": 59643
},
{
"icon_id": "762208",
"name": "警告",
"font_class": "-alert",
"unicode": "e61c",
"unicode_decimal": 58908
},
{
"icon_id": "15603541",
"name": "alert",
"font_class": "-alert1",
"unicode": "e68e",
"unicode_decimal": 59022
},
{
"icon_id": "8372144",
"name": "gitee",
"font_class": "-gitee",
"unicode": "e608",
"unicode_decimal": 58888
},
{
"icon_id": "18789786",
"name": "Logo GitHub",
"font_class": "-github",
"unicode": "e607",
"unicode_decimal": 58887
},
{
"icon_id": "14007542",
"name": "dialog",
"font_class": "dialog",
"unicode": "e82a",
"unicode_decimal": 59434
},
{
"icon_id": "16188455",
"name": "地图",
"font_class": "_map",
"unicode": "e68a",
"unicode_decimal": 59018
},
{
"icon_id": "18195942",
"name": "编辑器",
"font_class": "bianjiqi",
"unicode": "e7bd",
"unicode_decimal": 59325
},
{
"icon_id": "9434384",
"name": "divider",
"font_class": "divider",
"unicode": "e6b3",
"unicode_decimal": 59059
},
{
"icon_id": "7038155",
"name": "按钮",
"font_class": "anniu",
"unicode": "e642",
"unicode_decimal": 58946
},
{
"icon_id": "16859933",
"name": "按钮",
"font_class": "-button",
"unicode": "e648",
"unicode_decimal": 58952
},
{
"icon_id": "17692220",
"name": "按钮",
"font_class": "-button1",
"unicode": "e705",
"unicode_decimal": 59141
},
{
"icon_id": "5278848",
"name": "加号",
"font_class": "add",
"unicode": "e602",
"unicode_decimal": 58882
},
{
"icon_id": "13562655",
"name": "workbench_personal center_secondary password",
"font_class": "-password",
"unicode": "e600",
"unicode_decimal": 58880
},
{
"icon_id": "14007479",
"name": "lock",
"font_class": "-lock",
"unicode": "e822",
"unicode_decimal": 59426
},
{
"icon_id": "11889820",
"name": "HTML",
"font_class": "-html",
"unicode": "e622",
"unicode_decimal": 58914
},
{
"icon_id": "886505",
"name": "时间",
"font_class": "-time",
"unicode": "e61a",
"unicode_decimal": 58906
},
{
"icon_id": "1634604",
"name": "chart-area",
"font_class": "-chart1",
"unicode": "e60f",
"unicode_decimal": 58895
},
{
"icon_id": "1708415",
"name": "时间范围",
"font_class": "-timerange",
"unicode": "e601",
"unicode_decimal": 58881
},
{
"icon_id": "2883120",
"name": "多选项",
"font_class": "-checkbox",
"unicode": "e629",
"unicode_decimal": 58921
},
{
"icon_id": "3541137",
"name": "日期",
"font_class": "-date",
"unicode": "e7b2",
"unicode_decimal": 59314
},
{
"icon_id": "5112503",
"name": "编辑器",
"font_class": "-setting",
"unicode": "e7fe",
"unicode_decimal": 59390
},
{
"icon_id": "5672533",
"name": "滑块",
"font_class": "-slider",
"unicode": "e620",
"unicode_decimal": 58912
},
{
"icon_id": "5920510",
"name": "表格",
"font_class": "-table",
"unicode": "e802",
"unicode_decimal": 59394
},
{
"icon_id": "5981330",
"name": "stream list",
"font_class": "-list",
"unicode": "e7dc",
"unicode_decimal": 59356
},
{
"icon_id": "6664173",
"name": "input",
"font_class": "-input",
"unicode": "e619",
"unicode_decimal": 58905
},
{
"icon_id": "7036392",
"name": "开关 关",
"font_class": "-switch",
"unicode": "e62f",
"unicode_decimal": 58927
},
{
"icon_id": "8036637",
"name": "评分",
"font_class": "-rate",
"unicode": "e829",
"unicode_decimal": 59433
},
{
"icon_id": "8171626",
"name": "附 件",
"font_class": "-att",
"unicode": "e624",
"unicode_decimal": 58916
},
{
"icon_id": "9529563",
"name": "html",
"font_class": "-doc",
"unicode": "e621",
"unicode_decimal": 58913
},
{
"icon_id": "9702638",
"name": "编辑器",
"font_class": "-editor",
"unicode": "e614",
"unicode_decimal": 58900
},
{
"icon_id": "9750331",
"name": "textarea",
"font_class": "-textarea",
"unicode": "e603",
"unicode_decimal": 58883
},
{
"icon_id": "10995620",
"name": "定位",
"font_class": "-location",
"unicode": "e604",
"unicode_decimal": 58884
},
{
"icon_id": "11020734",
"name": "栅格",
"font_class": "-col",
"unicode": "e69d",
"unicode_decimal": 59037
},
{
"icon_id": "11809961",
"name": "分割线",
"font_class": "-divider",
"unicode": "e73e",
"unicode_decimal": 59198
},
{
"icon_id": "12263722",
"name": "日期范围",
"font_class": "-daterange",
"unicode": "e73b",
"unicode_decimal": 59195
},
{
"icon_id": "12278783",
"name": "下 拉",
"font_class": "-select",
"unicode": "e63c",
"unicode_decimal": 58940
},
{
"icon_id": "13176332",
"name": "单选",
"font_class": "-radio",
"unicode": "e605",
"unicode_decimal": 58885
},
{
"icon_id": "13225654",
"name": "chart-line",
"font_class": "-chart",
"unicode": "e606",
"unicode_decimal": 58886
},
{
"icon_id": "14006818",
"name": "计数器",
"font_class": "-inputNumber",
"unicode": "e6a7",
"unicode_decimal": 59047
},
{
"icon_id": "14066795",
"name": "tab",
"font_class": "-tab",
"unicode": "e6b4",
"unicode_decimal": 59060
}
]
}
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="12" height="12" viewBox="0 0 12 12">
<image id="首页" y="0.5" width="12" height="11" xlink:href="data:img/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAALCAYAAABLcGxfAAAA1UlEQVQokYWOsUqCYRSGH/+iEMpoqEncEhrE3VXcuoDuQ6IL0ckuoKEhaBMXaXFLWrqA0HBwbAt85MAX/HwoHjh857zneT9e1Ly76lz9UB/yew4/qhv1Xm2qa3WyzzBOwG1JK9SpulLr/4aG+q7OErAr5kBdqL1YvtXfHVDeT6rHwBDocLh+gJcC+AROMvwKuMm0S2AZhhpQyeBn4A3olfQNUA1DxPorHdrAF/AK3JX0YI4CDmcLOEviOXAKGECao+pAUVEj0ihlDEPsF+mjqGV6r4H+FhxB2YcETV9JAAAAAElFTkSuQmCC"/>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="12" height="12" viewBox="0 0 12 12">
<image id="告警管理" x="-1" y="-1" width="14" height="14" xlink:href="data:img/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAABS0lEQVQokX3Sv0vXYRAH8Nc3ysoQCyohI2moISfRfyDBIWhrCUFCaBKKGoSmmvoDmqIc+gcsCIkgaFLQMRpcBLPIsR+TOFQXp/eFJ60O7vN87t539zz3vutEhH/IFfTi+d/g/yW+xjkM70NwoM4+LGGiwd7gRWNfxEq3UDexg4NYxxje4TrGsYqrWKv4zk5GPrXRidiVhxExGBGnIuJu+e60sfnpi4gTpSlTe4qljhV2ISKOR0R/kvO2SMgn/cA1nMcrHMUklvEMIziE7ezrRhn3cLJ6nsdi9foSp/ENXzGtCPlcwekcqv8nmMElPC7fMXzHx5bVrvys8yk+oR8PyvfHwPPGdqZHGjvp32rsntLd+dXm3MZs9fqhsLNVeKOxD2MO9zPxDDZxC+8xUIFJRj69S9iX2t0FXM7EvOURRvFrby+N5MYktombvwGs+p53uBB4fAAAAABJRU5ErkJggg=="/>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="12" height="12" viewBox="0 0 12 12">
<image id="平台设置" width="12" height="12" xlink:href="data:img/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAYAAABWdVznAAABH0lEQVQokV2RPSjFYRTGf66v2x0sDFIXg2sQIaOFUWazRcrHoEzKakPJ4ApZlLLcQcqgTAwyW2wykFISZfHTe++Rf06d932ec07nvOd5UbO+oB6pnRFbV8tqy29NXTqAJmAt7iegH3gHvoBXYBBYBe6y3Stqe+CC2pXJHasTCeeoWStQDzQE/wQe+bMPoFhl6qJ6o05FtzH1RN1TZyNWUi/UjUSuI5BwUT1T+9TmwJORy6mb6UlXwH0MT2PfqsvVFr4FBiL3DZSTSpVQYimUSWp1AA9Ab8SfgWVgPI1KGm+ruxlV5tUVNR98Tr1Uh7Ky7md2+e8H6khW1kagB+gGCsAWsAOUgDwwDLSlwt+fTjYKzADtwDnwAkzHn5wCh4A/YfIQmkKOjGcAAAAASUVORK5CYII="/>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="12" height="12" viewBox="0 0 12 12">
<image id="生产厂商" width="12" height="12" xlink:href="data:img/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAYAAABWdVznAAABG0lEQVQokW3QPUsQUBTG8Z/iS1lBomtzU5NCNiRuQQ5+gVAIitYWl8APIDS6uURDTYWrm0a7RmAO4hItLiIFRtQTp45g4YFz7z333ufe/3kkqVxOcphkv/MgyfM++ydrmEpynGQ6yZXOW0mOksz8LxjCTWzgA+76G++whqd4i+89/xF8wzHu4RkGsdJ7t3EDl/EEC/XNQpKtC3jfJHlwrq6+Foca4RNmsYQBvMAORrGK7Ua6dib42YcTLRjBj8a7XhcxjNMzpO0LkDaSPD5XbyZ5VC9U7OI+ttqhebzHL7zGQ3ysupBOMdai9X6g+MuhL3iFfUyXvSUo2+7gBC9bcBVzvS6LL2EGnwfKvlYfdcMVhTLejX/t/Uns/Qb8YcvTPw2WuQAAAABJRU5ErkJggg=="/>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="14" height="12" viewBox="0 0 14 12">
<image id="图层_19" data-name="图层 19" width="14" height="12" xlink:href="data:img/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAMCAYAAABSgIzaAAABCElEQVQokW2SP0sDQRDFf4mamEaIIJc2zV2wtLWQtNaC6VKkChH8Bgd3nUXIB4jphJAvIAgWIf5pBVMdNuly16oQUp0MjrJ3tw+m2LfzZubNbilNU0x4YdIChkBN6RUwiHxnY+btUsQFcJ5jR8DSJMoFmb1YgbMJH4EPYAt8Aq86bhbi0RZuEN+7QXxtu5P4X44XJuLtWGoBsogb9TUFqsq9RL4jE/wKvTA5BZ6BhXA60hrYB+pa7Ag4jHynYZre0WpnBS8GvDB5+zuW3CDuAZfAiY41jnznPScQGx2gDcyAO+l4a+RcAQdAN9dsorygDzRtz1GxcNnvBXsifAK+Nb70nMdDJgfmP68GamceNFjdAAAAAElFTkSuQmCC"/>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="11" height="14" viewBox="0 0 11 14">
<image id="地点" width="11" height="14" xlink:href="data:img/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAAOCAYAAAD5YeaVAAABMUlEQVQokWWSvy9EQRSFv92oKFcyOkGy0+gkKhKVAgUq8SOio1aIwk12oqbwH1CIQkOiV4hiJUIkTCEiSEyi0InCPrnMvLy8vdXMPd87c+7Mq2RZRirrwhqwAvQDr8C+F7OT9By2LhwCc7TXmRczqd1qBKcK4DYwDGzE/YR1YUkXHbGRwBMvZiv2mtaFQUDBeeCgGoUUvFUK0SrqybkJLALT1gXRE4Cx6Jp0kvNpwa0BXAO7Bf04h72YJ+C87R7+686LuS06ay0D3yVQsy6kTQ57Mc/ARQm+Sa5alXrjvRvYA7qANx0S6AE+gaO4/gHW1fkhCrNejD73CPCij+HFrAIzwL1mV1gn16/HrQsDXswjMOTFXFoX+rQP9Cr392/Eux2NA30BH0AN6NSowJUXs/kLKj9euCTXiIAAAAAASUVORK5CYII="/>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="12" height="12" viewBox="0 0 12 12">
<image id="系统管理" width="12" height="12" xlink:href="data:img/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAYAAABWdVznAAAA80lEQVQokY2RsUoDQBBEnxICMaKSSg1WgtgGLP0EwUI7IT8hduYjUmol1taSSgujoK2FnZWFEBBiI6jwZHUDpynMwMHu7c7s3tyU+gQ0mQyDIAicAP1/KDWggz/YDN4E53o62XNjeuOYB1YrQKy0BDSKlpciDrEPYAjsxJihvzFQG2ozV4z6ulpTqzFhFjgAesACUAdWgHPgNiccA8vA2ejRfXVfbaXqjHqXtcNii8Uonqq9vLhJwmfm7UIg8FZaeak+ZLwXFuaUNbWrvqu7o+arVLjIvKK+/jEjsBU/HdZtAFXgGXgEWkAbOALuge1vI6D+BQSZFivDzo07AAAAAElFTkSuQmCC"/>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="12" height="12" viewBox="0 0 12 12">
<image id="设备管理" width="12" height="12" xlink:href="data:img/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAYAAABWdVznAAAA/klEQVQokYWRPysFUBiHH6KuZJE/oWSQxWKx+BpKhsvNRzAYfABfwIQyKJPFoEyK6JZYsIliuINkMFwmt0dv96jjGLx1hvP+3l/n95y3QyWrYWADGAJawCmwmQ908rvmgWXgHvgA1gudruI+BuwBa+l+8Z/hFtgHepK5vzQQDMWZVl/VHbWv1PMX5hJsA/gEmsAMMAjcAY8x9PNLi8AWUI9eMnSnyL3AKDCVM4wDh8DKn8ztuswZdtUn9U09UgeyzDX1XG2qJ2o1mu/qrDqpNtSFzFBXt9UJ9Vg9i8W9ANcJ6gGoZFG+kvYM3MT2gyE2GrAhBstVkX0VWAJGgINvUm2gs7a/fSsAAAAASUVORK5CYII="/>
</svg>
export default {
created() {
// this.getData();
},
beforeDestroy() {
clearTimeout(this.loadingTimer);
},
methods: {
// 渲染前置处理
beforeRender(data) {
return data
},
// 渲染后置处理
afterRender(data) {
},
// 提交表单的前置处理
beforeSubmit(data) {
return data
},
// 提交表单的后置处理, 会阻断默认的回退行为
afterSubmit(data) {
this.$router.go(-1);
},
// 开启、关闭
changePath(path) {
this.pageInfo.list = path + "/list";
this.pageInfo.del = path + "/delete";
this.pageInfo.add = path + "/add";
this.pageInfo.edit = path + "/edit";
this.pageInfo.view = path + "/view";
},
// 默认拉取数据
getData() {
this.loading = true;
this.$get(this.urls.currUrl || this.pageInfo.currUrl, this.query)
.then(({ data }) => {
const res = this.beforeRender(data);
//转化枚举类型字段的number值为arrays
res.entity = this.util_toArrays(res.entity, this.toArrays);
// 转化枚举类型字段的number值为string
res.entity = this.util_toString(res.entity, this.toString);
//
res.entity = this.util_toDateStr(res.entity, this.toDate);
this.form = Object.assign({}, this.form, res.entity);
this.dict = Object.assign({}, this.dict, res.dict);
this.afterRender(res);
})
.catch(error => {
this.$message.error(error.message)
throw error
})
.then(data => {
clearTimeout(this.loadingTimer);
this.loadingTimer = setTimeout(() => {
this.loading = false;
}, 300);
})
},
// 提交表单
submitForm(ref) {
const el = this.$refs.form;
el.validate((valid) => {
if (!valid) return;
this.loading = true;
this.$post(this.urls.saveUrl || this.pageInfo.saveUrl, this.beforeSubmit(this.form))
.then(res => {
this.$message.success(res.msg);
this.afterSubmit(res);
})
.catch(error => {
this.$message.error(error.message);
})
.then(data => {
clearTimeout(this.loadingTimer);
this.loadingTimer = setTimeout(() => {
this.loading = false;
}, 200);
})
});
},
// 复制一个数组或对象
util_copy(data) {
return JSON.parse(JSON.stringify(data))
},
// 工具方法,把数字转化为字符串
util_toString(data, array) {
//原始数据
const dataCopy = Object.assign({}, data);
array.forEach(item => {
//如果相等做操作
dataCopy[item] = dataCopy[item] === undefined ? '' : dataCopy[item] + '';
})
return dataCopy;
},
// 工具方法,把字符串转化为数组
util_toArrays(data, array) {
const dataCopy = Object.assign({}, data);
array.forEach(item => {
dataCopy[item] = dataCopy[item] === undefined ? [] : dataCopy[item].split(",");
})
return dataCopy;
},
// 工具方法,把字符串转化为格式化日期
util_toDateStr(data, array) {
const dataCopy = Object.assign({}, data);
array.forEach(item => {
dataCopy[item] = dataCopy[item] === undefined ? '' : this.util_formatterDate(dataCopy[item]);
})
return dataCopy;
},
util_formatterDate(time) {
let date = new Date(Number(time));
let Y = date.getFullYear() + '-';
let M = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1) + '-';
let D = this.panLeft(date.getDate()) + ' ';
let h = this.panLeft(date.getHours()) + ':';
let m = this.panLeft(date.getMinutes()) + ':';
let s = this.panLeft(date.getSeconds());
return Y + M + D + h + m + s;
},
panLeft(num) {
return num < 10 ? '0' + num : num;
},
// 从dict字段暴力取值,取不到则返回原值
util_formatter(key, val) {
try {
return this.dict[key][val]
} catch (error) {
return val;
}
},
resetForm(refName) {
setTimeout(() => {
this.$nextTick(() => {
if (this.$refs[refName]) {
this.$refs[refName].resetFields();
}
});
}, 0);
}
},
computed: {
pageInfo() {
let currUrl = this.$route.path;
let urlArray = currUrl.split('/');
let type = urlArray.pop();
urlArray.push('save');
let saveUrl = urlArray.join('/');
urlArray.pop();
urlArray.push('edit');
let editUrl = urlArray.join('/');
urlArray.pop();
urlArray.push('add');
let addUrl = urlArray.join('/');
urlArray.pop();
urlArray.push('view');
let viewUrl = urlArray.join('/');
return {
type,
currUrl,
saveUrl,
editUrl,
addUrl,
viewUrl,
};
},
},
data() {
return {
loadingTimer: null,
loading: false, // ajax请求状态
query: this.$route.query, // ajax请求参数
urls: {}, // 用户自定义的请求地址,内容和pageInfo等同
form: {}, // 表单数据
extendFormData: {}, // 额外的表单数据
rules: {}, // 表单验证规则
dict: {}, // 数据字典
toString: [], // 需要把number转化为string的表单字段name数组
toArrays: [], // 需要把number转化为arrays的表单字段name数组
toDate: [], // 需要把number转化为date的表单字段name数组
}
}
}
import axios from 'axios';
export default {
mounted() {
},
beforeDestroy () {
this.source.cancel('自动取消ajax操作');
clearTimeout(this.loadingTimer);
},
methods: {
beforeFecth() {
return Promise.resolve();
},
// 表格接收数据前
beforeRender(data){return data},
// 表格接收数据后
afterRender(data){},
// 默认拉取数据
async getTreeData() {
},
handleNodeClick(node) {
},
renderContent: function (h, { node, data, store }) {
return (
<span>
<i style="font-size:16px;color:#409EFF" class={data.icon}></i>
<span style="padding-left: 2px;font-size:14px">{node.label}</span>
</span>
);
},
async loadNode(node, resolve) {
if (node.level === 0) {
return;
}
resolve(data.result);
// this.$post("/area/getListByParentId", {
// parentId: node.data.id,
// }).then(({ data }) => {
// resolve(data.result);
// });
},
refreshNodeBy(id) {
let node = this.$refs.areaTree.getNode(this.currentNode.id); // 通过节点id找到对应树节点对象
node.loaded = false;
node.expand(); // 主动调用展开节点方法,重新查询该节点下的所有子节点
this.toView(this.currentNode);
},
},
data() {
return {
treeProps: {
id: "id",
label: "label",
areaCode:"areaCode",
type: "type",
isLeaf: "isLeaf",
children: "children",
icon: "icon",
},
areaData:[],
currentNode:{},
}
}
}
export default {
created() {
//this.getData();
},
beforeDestroy() {
clearTimeout(this.loadingTimer);
},
methods: {
// 渲染前置处理
beforeRender(data) {
return data
},
// 渲染后置处理
afterRender(data) {
},
// 默认拉取数据
getData() {
this.loading = true;
this.$get(this.urls.currUrl || this.pageInfo.currUrl, this.query)
.then(({ data }) => {
const res = this.beforeRender(data);
//转化枚举类型字段的number值为arrays
res.entity = this.util_toArrays(res.entity, this.toArrays);
// 转化枚举类型字段的number值为string
res.entity = this.util_toString(res.entity, this.toString);
//
res.entity = this.util_toDateStr(res.entity, this.toDate);
this.form = Object.assign({}, this.form, res.entity);
this.dict = Object.assign({}, this.dict, res.dict);
console.log("entity",res.entity)
this.afterRender(res);
})
.catch(error => {
console.error(error)
this.$message.error(error.message);
})
.then(data => {
clearTimeout(this.loadingTimer);
this.loadingTimer = setTimeout(() => {
this.loading = false;
}, 300);
})
},
// 复制一个数组或对象
util_copy(data) {
return JSON.parse(JSON.stringify(data))
},
// 工具方法,把数字转化为字符串
util_toString(data, array) {
//原始数据
const dataCopy = Object.assign({}, data);
array.forEach(item => {
//如果相等做操作
dataCopy[item] = dataCopy[item] === undefined ? '' : dataCopy[item] + '';
})
return dataCopy;
},
// 工具方法,把字符串转化为数组
util_toArrays(data, array) {
const dataCopy = Object.assign({}, data);
array.forEach(item => {
dataCopy[item] = dataCopy[item] === undefined ? [] : dataCopy[item].split(",");
})
return dataCopy;
},
// 工具方法,把字符串转化为格式化日期
util_toDateStr(data, array) {
const dataCopy = Object.assign({}, data);
array.forEach(item => {
dataCopy[item] = dataCopy[item] === undefined ? '' : this.util_formatterDate(dataCopy[item]);
})
return dataCopy;
},
util_formatters(key, val) {
try {
return val.split(",").map((i) => this.util_formatter(key, i)).join(",");
} catch (error) {
return val;
}
},
util_formatterDate(time) {
let date = new Date(Number(time));
let Y = date.getFullYear() + '-';
let M = (date.getMonth()+1 < 10 ? '0'+(date.getMonth()+1) : date.getMonth()+1) + '-';
let D = this.panLeft(date.getDate()) + ' ';
let h = this.panLeft(date.getHours()) + ':';
let m = this.panLeft(date.getMinutes()) + ':';
let s = this.panLeft(date.getSeconds());
return Y+M+D+h+m+s;
},
panLeft(num){
return num < 10 ? '0'+num : num;
},
// 从dict字段暴力取值,取不到则返回原值
util_formatter(key, val) {
try {
return this.dict[key][val]
} catch (error) {
return val;
}
}
},
computed: {
pageInfo() {
let currUrl = this.$route.path;
let urlArray = currUrl.split('/');
let type = urlArray.pop();
urlArray.push('save');
let saveUrl = urlArray.join('/');
urlArray.pop();
urlArray.push('edit');
let editUrl = urlArray.join('/');
urlArray.pop();
urlArray.push('add');
let addUrl = urlArray.join('/');
urlArray.pop();
urlArray.push('view');
let viewUrl = urlArray.join('/');
return {
type,
currUrl,
saveUrl,
editUrl,
addUrl,
viewUrl,
};
},
},
data() {
return {
loadingTimer: null,
loading: false, // ajax请求状态
query: this.$route.query, // ajax请求参数
urls: {}, // 用户自定义的请求地址,内容和pageInfo等同
form: {}, // 表单数据
extendFormData: {}, // 额外的表单数据
rules: {}, // 表单验证规则
dict: {}, // 数据字典
toString: [], // 需要把number转化为string的表单字段name数组
toArrays: [], // 需要把number转化为arrays的表单字段name数组
toDate: [], // 需要把number转化为date的表单字段name数组
}
}
}
exports.install = function (Vue) {
// 把需要暴露出去的方法挂载到Vue原型上,避免了全局变量过多的问题
Vue.prototype.refreshData = function () {
console.log("刷新设备列表")
const component = findComponentDownward(this, 'Device')
console.log("component",component)
if(component){
component.getData()
}
}
}
/**
* 由一个组件,向下找到最近的指定组件
* @param {*} context 当前上下文,比如你要基于哪个组件来向上寻找,一般都是基于当前的组件,也就是传入 this
* @param {*} componentName 要找的组件的 name
*/
function findComponentDownward(context, componentName) {
const childrens = context.$children
let children = null
if (childrens.length) {
for (const child of childrens) {
const name = child.$options.name
if (name === componentName) {
children = child
break
} else {
children = findComponentDownward(child, componentName)
if (children) break
}
}
}
return children
}
\ No newline at end of file
/**
* 本地存储函数
*/
const local = {
// 设置
setLocal(key, val) {
localStorage.setItem(key, JSON.stringify(val));
},
// 获取
getLocal(key) {
return JSON.parse(localStorage.getItem(key));
},
// 删除本地存储
removeLocal(key){
localStorage.removeItem(key)
},
// 清空本地存储
clearLocal() {
localStorage.clear();
},
};
// 暴露
export default local;
\ No newline at end of file
/**
* 本地存储函数
*/
const session = {
// 设置
setSession(key, val) {
sessionStorage.setItem(key, JSON.stringify(val));
},
// 获取
getSession(key) {
return JSON.parse(sessionStorage.getItem(key));
},
// 删除本地存储
removeSession(key) {
sessionStorage.removeItem(key)
},
// 清空本地存储
clearSession() {
sessionStorage.clear();
},
};
// 暴露
export default session;
\ No newline at end of file
<template lang="html">
<div style="width:100%;height:100%;">
<div class="container">
<!-- <div class="search-box">
<input
v-model="searchKey"
type="search"
id="search">
<button @click="searchByHand">搜索</button>
<div class="tip-box" id="searchTip"></div>
</div> -->
<!--
amap-manager: 地图管理对象
vid:地图容器节点的ID
zooms: 地图显示的缩放级别范围,在PC上,默认范围[3,18],取值范围[3-18];在移动设备上,默认范围[3-19],取值范围[3-19]
center: 地图中心点坐标值
plugin:地图使用的插件
events: 事件
-->
<el-amap class="amap-box"
:amap-manager="amapManager"
:vid="'amap-vue'"
:zoom="zoom"
:plugin="plugin"
:center="center"
:events="events"
>
<!-- 标记 -->
<el-amap-marker v-for="(marker, index) in markers" :position="marker" :key="index"></el-amap-marker>
</el-amap>
</div>
</div>
</template>
<script>
import { AMapManager, lazyAMapApiLoaderInstance } from "vue-amap";
let amapManager = new AMapManager();
export default {
name: "AMap",
data() {
let self = this;
return {
address: null,
searchKey: "",
amapManager,
markers: [],
searchOption: {
city: "全国",
citylimit: true,
},
center: [112.938888, 28.228272],
zoom: 17,
lng: 0,
lat: 0,
loaded: false,
events: {
init() {
lazyAMapApiLoaderInstance.load().then(() => {
self.initSearch();
});
},
// 点击获取地址的数据
click(e) {
self.markers = [];
let { lng, lat } = e.lnglat;
self.lng = lng;
self.lat = lat;
self.center = [lng, lat];
self.markers.push([lng, lat]);
// 这里通过高德 SDK 完成。
let geocoder = new AMap.Geocoder({
radius: 1000,
extensions: "all",
});
geocoder.getAddress([lng, lat], function (status, result) {
if (status === "complete" && result.info === "OK") {
if (result && result.regeocode) {
console.log(result.regeocode.formattedAddress); //控制台打印地址
self.address = result.regeocode.formattedAddress;
self.searchKey = result.regeocode.formattedAddress;
self.$nextTick();
}
}
});
},
},
// 一些工具插件
plugin: [
{
pName: "Geocoder",
events: {
init(o) {
//console.log("一些工具插件--地址"+o.getAddress())
},
},
},
{
// 定位
pName: "Geolocation",
events: {
init(o) {
// o是高德地图定位插件实例
o.getCurrentPosition((status, result) => {
if (result && result.position) {
// 设置经度
self.lng = result.position.lng;
// 设置维度
self.lat = result.position.lat;
// 设置坐标
self.center = [self.lng, self.lat];
self.markers.push([self.lng, self.lat]);
// load
self.loaded = true;
// 页面渲染好后
self.$nextTick();
}
});
},
},
},
{
// 工具栏
pName: "ToolBar",
events: {
init(instance) {
//console.log("工具栏:"+instance);
},
},
},
{
// 鹰眼
pName: "OverView",
events: {
init(instance) {
//console.log("鹰眼:"+instance);
},
},
},
{
// 地图类型
pName: "MapType",
defaultType: 0,
events: {
init(instance) {
//console.log("地图类型:"+instance);
},
},
},
{
// 搜索
pName: "PlaceSearch",
events: {
init(instance) {
//console.log("搜索:"+instance)
},
},
},
],
};
},
methods: {
initSearch() {
let vm = this;
let map = this.amapManager.getMap();
AMapUI.loadUI(["misc/PoiPicker"], function (PoiPicker) {
var poiPicker = new PoiPicker({
input: "search",
placeSearchOptions: {
map: map,
pageSize: 10,
},
suggestContainer: "searchTip",
searchResultsContainer: "searchTip",
});
vm.poiPicker = poiPicker;
// 监听poi选中信息
poiPicker.on("poiPicked", function (poiResult) {
// console.log(poiResult)
let source = poiResult.source;
let poi = poiResult.item;
if (source !== "search") {
poiPicker.searchByKeyword(poi.name);
} else {
poiPicker.clearSearchResults();
vm.markers = [];
let lng = poi.location.lng;
let lat = poi.location.lat;
let address = poi.cityname + poi.adname + poi.name;
vm.center = [lng, lat];
vm.markers.push([lng, lat]);
vm.lng = lng;
vm.lat = lat;
vm.address = address;
vm.searchKey = address;
}
});
});
},
searchByHand() {
if (this.searchKey !== "") {
this.poiPicker.searchByKeyword(this.searchKey);
}
},
},
};
</script>
<style lang="css">
.container {
width: 100%;
height: 100%;
position: relative;
left: 50%;
top: 50%;
transform: translate3d(-50%, -50%, 0);
border: 1px solid #999;
}
.search-box {
position: absolute;
z-index: 5;
width: 30%;
left: 13%;
top: 10px;
height: 30px;
}
.search-box input {
float: left;
width: 80%;
height: 100%;
border: 1px solid #30ccc1;
padding: 0 8px;
outline: none;
}
.search-box button {
float: left;
width: 20%;
height: 100%;
background: #30ccc1;
border: 1px solid #30ccc1;
color: #fff;
outline: none;
}
.tip-box {
width: 100%;
max-height: 260px;
position: absolute;
top: 30px;
overflow-y: auto;
background-color: #fff;
}
</style>
<script>
export default {
props: {
handleSelectionChange: {
type: Function,
required: false,
default: () => {},
},
handleRowClick: {
type: Function,
required: false,
default: () => {},
},
tableRowClassName: {
type: Function,
required: false,
default: () => {},
},
tableData: {
type: Array,
required: false,
default: () => [],
},
columns: {
type: Array,
required: false,
default: () => [],
},
dict: {
type: Object,
required: false,
default: () => {},
},
},
methods: {
// 开标状态
bidStatus(v) {
switch (v) {
case 0:
return "type1";
case 4:
return "type3";
default:
return "type2";
}
},
// 格式化
formatter(v, code) {
return this.dict[code] ? this.dict[code][v] : "--";
},
cell(row, column, cellValue, index) {
column.property = column.prop;
if (column.formatter)
return column.formatter(row, column, cellValue, index);
return false;
},
},
data() {
return {
src: require(`@/assets/images/1.png`),
};
},
render() {
return (
<div>
{this.tableData.map((item, index) => {
console.log(item);
let arrs = this.columns
.filter((i) => !i.type)
.filter((i) => !i.title)
.filter((i) => i.flow);
return (
<el-row>
<el-row gutter="20">
<el-col span="22">
{" "}
<div
onClick={() =>
this.handleRowClick(item, this.columns, null)
}
>
<el-descriptions
column={arrs.length}
size="small"
title={this.columns
.filter((i) => i.title)
.map((column) => item[column.prop])}
>
{arrs
.filter((i) => i.label != "操作")
.map((column) => {
return (
<el-descriptions-item label={column.label}>
{this.cell(
item,
column,
item[column.prop],
index
) || item[column.prop]}
</el-descriptions-item>
);
})}
</el-descriptions>
</div>
{arrs
.filter((i) => i.label == "操作")
.map((column) => {
return (
<div
style="margin-left:5px;margin-top:3px"
label={column.label}
>
{this.cell(item, column, item[column.prop], index) ||
item[column.prop]}
</div>
);
})}
</el-col>
<el-col span="2">
<span
class="state_box"
class={[this.bidStatus(item.projectOpenBidStatus)]}
>
{this.formatter(
item.projectOpenBidStatus,
"projectOpenBidStatus"
)}
</span>
</el-col>
</el-row>
<el-row>
{" "}
<el-divider />
</el-row>
</el-row>
);
})}
</div>
);
},
};
</script>
<style lang="less" scoped>
.state_box {
position: relative;
width: 80px;
height: 80px;
text-align: center;
line-height: 80px;
right: 15px;
top: 10px;
display: inline-block;
border-radius: 50%;
transform: rotateZ(45deg);
font-size: 13px;
}
.type1 {
color: tomato;
border: 2px solid tomato;
&:extend(.state_box);
}
.type2 {
color: #1334a7;
border: 2px solid #1334a7;
&:extend(.state_box);
}
.type3 {
color: #999;
border: 2px solid #999;
&:extend(.state_box);
}
</style>
\ No newline at end of file
<template>
<el-table
v-loading="loading"
:data="tableData"
row-key="id"
border
@row-click="handleRowClick"
:row-class-name="tableRowClassName"
:default-expand-all="expand"
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
>
<el-table-column
v-for='column in columns'
:key='column.prop'
:type="column.type"
:prop="column.prop"
:label="column.label"
:width="column.width"
:show-overflow-tooltip="column.tooltip"
:align="column.align || 'left'"
:formatter='column.formatter'
>
</el-table-column>
</el-table>
</template>
<script>
export default {
props: {
handleSpanMethod: {
type: Function,
required: false,
default: () => {}
},
handleRowClick: {
type: Function,
required: false,
default: () => {}
},
tableRowClassName: {
type: Function,
required: false,
default: () => {}
},
loading: {
type: Boolean,
required: false,
default: true
},
expand: {
type: Boolean,
required: false,
default: true
},
tableData: {
type: Array,
required: false,
default: () => []
},
columns: {
type: Array,
required: false,
default: ()=> [],
}
},
computed: {
emptyText() {
return (!this.loading && !this.tableData.length) ? '暂无数据' : '加载中...'
},
},
data() {
return {}
}
}
</script>
<template>
<span>
<!-- 开启confirm时,操作之前会先调动确认窗口 -->
<el-popover
v-if='confirm'
placement="top"
width="160"
v-model="visible">
<p>确认操作?</p>
<div style="text-align: right; margin: 0">
<el-button size="mini" type="text" @click="visible = false">取消</el-button>
<el-button type="primary" size="mini" @click="statusClick">确定</el-button>
</div>
<label slot="reference" class="my-compontent-switch"
:checked='checked'>
<span>{{text}}</span>
</label>
</el-popover>
<!-- 直接操作 -->
<label
v-else
class="my-compontent-switch"
:checked='checked'
@click='statusClick'
>
<span>{{text}}</span>
</label>
</span>
</template>
<script>
export default {
props: {
value: Array,
row: Object,
confirm: Boolean,
on: {
type: Object,
default: ()=> {return {value: 1, text: '启用'}}
},
off: {
type: Object,
default: ()=> {return {value: 0, text: '停用'}}
},
url: String,
},
methods: {
async statusClick() {
console.log("value",this.value)
const enabled = this.row.enabled === this.on.value ? this.off.value : this.on.value;
const id = this.row.id;
//const getTokenUrl = this.url.replace('/save', '/edit');
// await this.$post(getTokenUrl, {id});
this.$post(this.url, {
enabled,
id,
})
.then(res=>{
// 更新数据
let table = JSON.parse(JSON.stringify(this.value))
console.log("table",table)
let {index, data} = this.find(table, id);
data.enabled = enabled;
table.splice(index, 1, data);
this.$emit("input", table);
this.$emit("change");
})
.catch(error=>{
this.$message.error(error.message);
})
.then(data=>{
this.visible = false;
})
},
find(list, id) {
let index = -1;
let data = null;
list.forEach((item, i)=>{
if(item.id === id){
index = i;
data = Object.assign({}, item);
return;
}
})
return {
index,
data,
}
},
},
computed: {
text() {
return this.row.enabled === this.on.value ? this.on.text : this.off.text;
},
checked() {
return this.row.enabled === this.on.value;
},
},
data() {
return {
visible: false,
}
}
}
</script>
<style lang="less">
.my-compontent-switch{
display: inline-flex;
align-items: center;
position: relative;
font-size: 12px;
line-height: 19px;
height: 20px;
vertical-align: middle;
&[checked] span{
border-color: #409eff;
background-color: #409eff;
padding:0 23px 0 10px;
&::after{
left: 100%;
margin-left: -17px;
}
}
span{
margin: 0;
display: inline-block;
position: relative;
height: 20px;
border: 1px solid #dcdfe6;
outline: none;
color: #fff;
padding:0 10px 0 23px;
border-radius: 10px;
box-sizing: border-box;
background: #dcdfe6;
cursor: pointer;
transition: border-color .3s,background-color .3s;
vertical-align: middle;
&::after{
content: "";
position: absolute;
top: 1px;
left: 1px;
border-radius: 100%;
transition: all .3s;
width: 16px;
height: 16px;
background-color: #fff;
}
}
}
</style>
<template>
<div :trigger="['click']" class="trigger" @click="ontrigger">
<slot>
<a class="ant-dropdown-link" @click="(e) => e.preventDefault()">
{{ siteName }} <i class="el-icon-arrow-down"></i>
</a>
</slot>
<div slot="overlay" class="select-site" v-if="show">
<div class="flex_row flex_align_c primary-color name">
<a-icon type="environment" style="margin-right: 10px" />
<span style="">{{ siteName }}</span>
</div>
<div class="site-list">
<span
v-for="(item, index) in sitelist"
:key="index"
:class="{ 'primary-color': item.id == checkid }"
@click="setSite(item)"
>{{ item.label }}</span
>
</div>
<div class="check-site">
<span>您的选择是:</span>
<span
v-for="(item, index) in checkarr"
:key="index"
@click="updataSite(item)"
>{{ index > 0 ? ">" : "" }}{{ item.label }}</span
>
</div>
<div class="site-btn">
<el-button
type="primary"
size="small"
style="margin-right: 10px"
@click="onSucessSite"
:disabled="isSite"
>确定</el-button
>
<el-button size="small" @click="show = false">取消</el-button>
</div>
</div>
</div>
</template>
<script>
// import { getSiteTree } from "@/services/businessMatter";
import session from "@/assets/utils/session";
// import Cookie from "js-cookie";
export default {
data() {
return {
sitelist: [],
show: false,
offsetLeft: 0,
checkarr: [], //选中站点
checkid: undefined, //最终选中站点
siteName: "",
isSite: true,
};
},
computed: {},
created() {
this.getwaitedListdata();
},
mounted() {},
methods: {
// 确认站点
onSucessSite() {
if (this.checkarr.length == 0) return;
let obj = this.checkarr[this.checkarr.length - 1];
this.clickSite(obj);
},
// 选中
setSite(obj) {
this.checkid = undefined;
// 为子节点不添加数据
let data = this.checkarr[this.checkarr.length - 1];
if (data && (data.isLeaf || data.children.length == 0)) {
// 如果为子节点更新最后一个数据
this.checkid = obj.id;
this.checkarr[this.checkarr.length - 1] = obj;
} else {
this.checkarr.push(obj);
if (obj.children && obj.children.length > 0) {
this.sitelist = obj.children;
}
}
if (obj && obj.type == "site") {
this.isSite = false;
} else {
this.isSite = true;
}
},
// 更新选中
updataSite(row) {
const { id } = row;
this.checkid = undefined;
let index = this.checkarr.findIndex((v) => v.id == id);
this.checkarr.length = index + 1;
this.sitelist = row.children;
if (row && row.type == "site") {
this.isSite = false;
} else {
this.isSite = true;
}
// this.getwaitedListdata(id);
},
getwaitedListdata() {
let url=process.env.VUE_APP_SITETREE_URL=='undefined'?'http://192.168.0.98:11078/base/site/siteTree':process.env.VUE_APP_SITETREE_URL
console.log("url:"+url)
console.log("url:"+process.env.VUE_APP_SITETREE_URL)
this.$get(url).then((res) => {
console.log(res.data);
const { siteTree } = res.data;
this.sitelist = siteTree;
let arr = [];
const treeFn = function (e) {
e.forEach((element) => {
arr.push(element);
if (element.children && element.children.length > 0) {
treeFn(element.children);
}
});
};
const siteid = session.getSession("siteid");
treeFn(siteTree);
const siteObj = arr.find((v) => v.id == siteid);
this.siteName = siteObj ? siteObj.label : "请选择站点";
});
},
clickSite(obj) {
session.setSession("siteid", obj.id);
this.show = false;
if (location.href.search(/token/gi) >= 0) {
setTimeout(() => {
location.reload();
});
} else {
location.reload();
}
},
ontrigger(e) {
if (e.target && e.target.nodeName == "A") {
this.show = !this.show;
}
},
},
};
</script>
<style lang="less" scoped>
.trigger {
display: inline-block;
position: relative;
}
.ant-dropdown-link {
padding: 0 20px;
font-size: 14px;
min-width: 200px;
color: #eee;
display: inline-block;
}
.select-site {
position: fixed;
left: 100px !important;
top: 65px;
background: #fff;
border-radius: 6px;
padding: 10px;
min-width: 60%;
max-width: 80%;
z-index: 9;
color: rgba(0, 0, 0, 0.8);
font-size: 14px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
.name {
font-size: 20px;
}
.site-list {
// padding: 10px 0;
border-top: 1px solid #ddd;
border-bottom: 1px solid #ddd;
overflow: hidden;
span {
float: left;
line-height: 1.5;
padding: 10px 20px;
cursor: pointer;
&:hover {
color: #1890ff;
}
}
}
.check-site,
.site-btn {
padding: 0 20px;
}
}
</style>
<template>
<el-image
:src="`${realSrc}`"
fit="cover"
:style="`width:${realWidth};height:${realHeight};`"
:preview-src-list="realSrcList"
>
<div slot="error" class="image-slot">
<i class="el-icon-picture-outline"></i>
</div>
</el-image>
</template>
<script>
export default {
name: "ImagePreview",
props: {
src: {
type: String,
required: true,
},
width: {
type: [Number, String],
default: "",
},
height: {
type: [Number, String],
default: "",
},
},
computed: {
realSrc() {
let real_src = this.src.split(",")[0];
return real_src;
},
realSrcList() {
let real_src_list = this.src.split(",");
let srcList = [];
real_src_list.forEach((item) => {
return srcList.push(item);
});
return srcList;
},
realWidth() {
return typeof this.width == "string" ? this.width : `${this.width}px`;
},
realHeight() {
return typeof this.height == "string" ? this.height : `${this.height}px`;
},
},
};
</script>
<style lang="scss" scoped>
.el-image {
border-radius: 5px;
background-color: #ebeef5;
box-shadow: 0 0 5px 1px #ccc;
::v-deep .el-image__inner {
transition: all 0.3s;
cursor: pointer;
&:hover {
transform: scale(1.2);
}
}
::v-deep .image-slot {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
color: #909399;
font-size: 30px;
}
}
</style>
// 地图组件
<template>
<div class="my-map">
<el-amap
ref="map"
vid="amapDetail"
:amap-manager="amapManager"
:center="center"
expandZoomRange
:zoom="20"
:pitch="65"
:rotation="45"
viewMode="3D"
:plugin="plugin"
:events="events"
class="amap-demo"
>
<div class="tuli1"><slot name="leftTop1"></slot></div>
<div class="tuli"><slot name="leftTop"></slot></div>
<div class="rightTop"><slot name="rightTop"></slot></div>
<!--marker -->
<el-amap-marker
v-for="(marker, index) in markers"
:key="'marker' + index"
:events="marker.events"
:position="marker.position"
:contentRender="contentRender"
:icon="marker.icon"
:extData="marker"
>
</el-amap-marker>
</el-amap>
</div>
</template>
<script>
import { formatterDate } from "@/assets/utils/index";
import { AMapManager } from "vue-amap";
let amapManager = new AMapManager();
export default {
name: "MapDetail",
props: {
value: {
type: Boolean,
},
originData: {
type: Object,
default: () => {},
},
markersData: {
type: Array,
required: false,
default: () => [],
},
},
computed: {
visible: {
get() {
return this.value;
},
set() {
this.$emit("input", false);
},
},
},
created() {
//this.refresh(this.markersData);
},
methods: {
formatterDate,
contentRender(h, params) {
//console.log(params.extData.extData.productId)
let value = params.extData.extData.productName;
console.log(">>>", params);
return <img src={require(`../assets/images/${value}.png`)} />;
},
getDeviceDetial() {
//获取设备列表
console.log("device siteId", this.info.siteId);
},
refresh(data) {
console.log("刷新数据", data);
// this.markersGroupData = data;
//this.$refs.map.clear();
let map = this.amapManager.getMap();
map.clearMap();
for (let group of data) {
for (let item of group.deviceList) {
//console.log("marker", item);
this.setMarker(item);
}
}
},
relocate(center) {
this.center = [center.lng, center.lat];
this.zoom = 20;
//重新定位中心点
},
setMarker(item) {
if (!item.lon && !item.lati) return;
let markerLabel = {
label: { content: item.deviceName, offset: [30, 70] },
position: [item.lon, item.lati],
extData: item,
events: {
click: (e) => {
console.log("getExtData", e.target.getExtData());
},
},
};
this.markers.push(markerLabel);
},
choose() {
this.$emit("input", false);
this.$emit("choose", JSON.parse(JSON.stringify(this.mapData)), (val) => {
//data = val;
console.log("callback:" + val);
});
},
},
data() {
return {
markersGroupData: [],
mapData: {},
info: {},
markers: [],
geocoder: null,
amapManager,
zoom: 20,
center: [104.007767, 30.568308],
marker: {},
// 一些工具插件
};
},
};
</script>
<style lang="less">
.tuli {
width: 400px;
top: 60px;
left: 34px;
position: absolute;
float: left;
background-color: rgba(255, 255, 255, 0.7);
}
.tuli1 {
width: 150px;
top: 10px;
left: 34px;
position: absolute;
float: left;
background-color: rgba(255, 255, 255, 0.7);
}
.rightTop {
width: 200px;
top: 0px;
right: 0px;
position: absolute;
float: right;
background-color: rgba(255, 255, 255, 1);
}
.amap-info-content {
position: relative;
background: #fff;
line-height: 1.4;
overflow: auto;
}
.my-map {
width: 100%;
height: 93vh;
.amap-demo {
position: relative;
width: 100%;
height: 100%;
.map-marker {
position: relative;
width: 30px;
height: 30px;
img {
position: absolute;
left: 50%;
transform: translate3d(-50%, -50%, 0);
}
.el-tag {
position: absolute;
color: #fff;
top: 30px;
transform: translateX(-50%);
background: #f56c6c;
}
}
.el-vue-search-box-container {
position: absolute;
top: -28px;
width: 100%;
box-shadow: 0 0 3px #ccc;
.search-tips {
width: 100%;
max-height: 300px;
}
}
}
}
</style>
<template>
<div class="right-board">
<el-tabs v-model="currentTab" class="center-tabs">
<el-tab-pane label="属性配置" name="field" />
</el-tabs>
<div class="field-box">
<el-scrollbar class="right-scrollbar">
<el-form size="small" label-width="100px" >
<div v-for="(item,index) in cmps" :key="index">
<component v-if="item.name === activeItem.compType" :getFormId="getFormId" :props="activeItem" :is="item.content"></component>
</div>
</el-form>
</el-scrollbar>
</div>
</div>
</template>
<script>
import reg from "./custom/register";
export default {
name:'configPanel',
data() {
return {
currentTab: 'field',
cmps:reg,
formIdArray:[]
}
},
props:{
activeItem: {
type: Object,
default:function(){
return {}
}
},
itemList: {
type: Array,
default:function(){
return []
}
}
},
created() {
this.cmps.forEach(c => {
c.content = require(`./custom/configs/${c.name}`).default;
});
},
methods:{
getFormId(itemId){
this.formIdArray = [];
Array.from(this.itemList,(item)=>{
if(item.compType === 'row'){
Array.from(item.columns,(column)=>{
Array.from(column.list,(col)=>{
if(col._id !== itemId){
this.formIdArray.push(col.id);
}
})
})
}else{
if(item._id !== itemId){
this.formIdArray.push(item.id);
}
}
})
return this.formIdArray;
}
}
}
</script>
<style scoped>
.field-box >>> .el-scrollbar__wrap{
overflow-x: hidden;
}
</style>
\ No newline at end of file
<template>
<div v-show="props.compType === 'Switch'">
<el-form-item label="ID">
<el-tooltip class="item" effect="dark" content="请注意,ID的修改可能会导致该组件相关事件失效!" placement="left">
<el-input class="input" v-model="props.id" @change="handlerChangeId"></el-input>
</el-tooltip>
</el-form-item>
<el-form-item label="标题">
<el-input class="input" v-model="props.label"></el-input>
</el-form-item>
<!-- <el-form-item label="表单栅格">
<el-slider class="input" v-model="props.span" :max="24" :min="1" :marks="{12:''}"></el-slider>
</el-form-item> -->
<el-form-item label="栅格间隔">
<el-input-number v-model="props.gutter" :min="0"></el-input-number>
</el-form-item>
<el-form-item label="标签宽度">
<el-input-number v-model="props.labelWidth" :min="1" :max="200"></el-input-number>
</el-form-item>
<el-form-item label="显示标签">
<el-switch v-model="props.showLabel" @change="handlerChangeLabel"></el-switch>
</el-form-item>
<el-form-item label="必填">
<el-switch v-model="props.required"></el-switch>
</el-form-item>
<el-form-item label="开启时颜色">
<el-color-picker v-model="props['active-color']"></el-color-picker>
</el-form-item>
<el-form-item label="关闭时颜色">
<el-color-picker v-model="props['inactive-color']"></el-color-picker>
</el-form-item>
<el-form-item label="开启时值">
<el-input class="input" v-model="props['active-value']"></el-input>
</el-form-item>
<el-form-item label="关闭时值">
<el-input class="input" v-model="props['inactive-value']"></el-input>
</el-form-item>
<el-form-item label="默认值">
<el-switch v-model="props.value"></el-switch>
</el-form-item>
</div>
</template>
<script>
import {changeId} from '../mixin'
export default {
name:"inputConfig",
props:['props','getFormId'],
components: {
},
mixins:[changeId],
data(){
return {}
},
methods:{
handlerChangeLabel(val){
this.props.labelWidth = val?'80':'1';
},
handlerChangeDisStatus(val){
this.props.readOnly = !val;
},
handlerChangeReadStatus(val){
this.props.disabled = !val;
}
},
mounted(){
}
}
</script>
<style scoped>
.input{
width:75%
}
</style>
\ No newline at end of file
<template>
<div v-show="props.compType === 'alert'">
<!-- <el-form-item label="字段名">
<el-input class="input" v-model="props"></el-input>
</el-form-item> -->
<el-form-item label="ID">
<el-tooltip class="item" effect="dark" content="请注意,ID的修改可能会导致该组件相关事件失效!" placement="left">
<el-input class="input" v-model="props.id" ></el-input>
</el-tooltip>
</el-form-item>
<el-form-item label="标题">
<el-input class="input" v-model="props.title"></el-input>
</el-form-item>
<el-form-item label="类型" >
<el-select v-model="props.type" placeholder="请选择">
<el-option label="success" value="success"/>
<el-option label="warning" value="warning"/>
<el-option label="error" value="error"/>
<el-option label="info" value="info"/>
</el-select>
</el-form-item>
<el-form-item label="辅助文字">
<el-input class="input" v-model="props.description"></el-input>
</el-form-item>
<el-form-item label="关闭">
<el-switch v-model="props.closable"></el-switch>
</el-form-item>
<el-form-item label="居中">
<el-switch v-model="props.center"></el-switch>
</el-form-item>
<el-form-item label="关闭按钮自定义文本">
<el-input class="input" v-model="props['close-text']"/>
</el-form-item>
<el-form-item label="显示图标">
<el-switch v-model="props['show-icon']"></el-switch>
</el-form-item>
<el-form-item label="主题">
<el-radio-group v-model="props.effect">
<el-radio-button label="light">light</el-radio-button>
<el-radio-button label="dark">dark</el-radio-button>
</el-radio-group>
</el-form-item>
</div>
</template>
<script>
/**
* input的配置项
*/
export default {
name:"buttonConfig",
props:{
props:{}
},
components:{
},
data(){
return {
}
},
methods:{
handlerShowLabel(val){
if(val){
this.props.labelWidth = 80;
}else{
this.props.labelWidth = 0;
}
}
},
mounted(){
}
}
</script>
<template>
<div v-show="props.compType === 'barCode'">
<!-- <el-form-item label="字段名">
<el-input class="input" v-model="props"></el-input>
</el-form-item> -->
<el-form-item label="ID">
<el-tooltip class="item" effect="dark" content="请注意,ID的修改可能会导致该组件相关事件失效!" placement="left">
<el-input class="input" v-model="props.id" ></el-input>
</el-tooltip>
</el-form-item>
<el-form-item label="显示标签">
<el-switch v-model="props.showLabel" @change="handlerShowLabel"></el-switch>
</el-form-item>
<el-form-item label="标签文字" v-show="props.showLabel">
<el-input class="input" v-model="props.label"></el-input>
</el-form-item>
<el-form-item label="标签长度" v-show="props.showLabel">
<el-input-number v-model="props.labelWidth" :min="1" :max="200"></el-input-number>
</el-form-item>
<el-form-item label="占用列数" v-show="props.span">
<el-input-number v-model="props.span" :min="1" :max="24"></el-input-number>
</el-form-item>
<el-form-item label="条码值">
<el-input v-model="props.value"></el-input>
</el-form-item>
<el-form-item label="条码颜色" v-show="props.lineColor">
<el-color-picker v-model="props.lineColor" @change="handlerChangeBarCode"/>
</el-form-item>
<el-form-item label="背景颜色" v-show="props.background">
<el-color-picker v-model="props.background" @change="handlerChangeBackground"/>
</el-form-item>
<!--暂不启用-->
<!-- <el-form-item label="条码宽度">
<el-input-number v-model="props.width" :min="1" :max="10" :step="1"></el-input-number>
</el-form-item> -->
<el-form-item label="条码高度">
<el-input-number v-model="props.height" :min="10" :max="100" :step="1"></el-input-number>
</el-form-item>
<el-form-item label="显示值">
<el-switch v-model="props.displayValue"></el-switch>
</el-form-item>
</div>
</template>
<script>
/**
* input的配置项
*/
export default {
name:"buttonConfig",
props:{
props:{}
},
components:{
},
data(){
return {
}
},
methods:{
handlerShowLabel(val){
if(val){
this.props.labelWidth = 80;
}else{
this.props.labelWidth = 0;
}
},
handlerChangeBarCode(val){
if(val == null){
this.props.lineColor = '#000';
}
},
handlerChangeBackground(val){
if(val == null){
this.props.background = '#fff';
}
}
},
mounted(){
}
}
</script>
<template>
<div v-show="props.compType === 'button'">
<el-form-item label="ID">
<el-tooltip class="item" effect="dark" content="请注意,ID的修改可能会导致该组件相关事件失效!" placement="left">
<el-input class="input" v-model="props.id" ></el-input>
</el-tooltip>
</el-form-item>
<el-form-item label="按钮文字">
<el-input class="input" v-model="props.text"></el-input>
</el-form-item>
<el-form-item label="显示标签">
<el-switch v-model="props.showLabel" @change="handlerShowLabel"></el-switch>
</el-form-item>
<el-form-item label="标签文字" v-show="props.showLabel">
<el-input class="input" v-model="props.label"></el-input>
</el-form-item>
<el-form-item label="标签长度" v-show="props.showLabel">
<el-input-number v-model="props.labelWidth" :min="1" :max="200"></el-input-number>
</el-form-item>
<el-form-item label="占用列数" v-show="props.span">
<el-input-number v-model="props.span" :min="1" :max="24"></el-input-number>
</el-form-item>
<el-form-item label="按钮类型" >
<el-select v-model="props.type" placeholder="请选择">
<el-option label="primary" value="primary"/>
<el-option label="success" value="success"/>
<el-option label="warning" value="warning"/>
<el-option label="danger" value="danger"/>
<el-option label="info" value="info"/>
<el-option label="text" value="text"/>
</el-select>
</el-form-item>
<el-form-item label="按钮大小">
<el-radio-group v-model="props.size">
<el-radio-button label="medium"></el-radio-button>
<el-radio-button label="small"></el-radio-button>
<el-radio-button label="mini"></el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item label="禁用">
<el-switch v-model="props.disabled"></el-switch>
</el-form-item>
<el-form-item label="简单样式">
<el-switch v-model="props.plain"></el-switch>
</el-form-item>
<el-form-item label="圆角">
<el-switch v-model="props.round"></el-switch>
</el-form-item>
<el-form-item label="圆形">
<el-switch v-model="props.circle"></el-switch>
</el-form-item>
<el-form-item label="图标">
<el-input placeholder="请选择图标" readonly v-model="props.icon">
<template slot="append" >
<i class="el-icon-picture" style="cursor: pointer;" @click="handlerSelectIcon"/>
</template>
</el-input>
</el-form-item>
<icon-dialog v-model="props.icon" :visible.sync="iconDialogVisible"/>
</div>
</template>
<script>
/**
* input的配置项
*/
export default {
name:"buttonConfig",
props:{
props:{}
},
data(){
return {
iconDialogVisible:false
}
},
methods:{
handlerShowLabel(val){
if(val){
this.props.labelWidth = 80;
}else{
this.props.labelWidth = 0;
}
},
handlerSelectIcon(){
this.iconDialogVisible = true;
}
},
mounted(){
}
}
</script>
<template>
<div v-show="props.compType === 'cascader'">
<!-- <el-form-item label="字段名">
<el-input class="input" v-model="props"></el-input>
</el-form-item> -->
<el-form-item label="ID">
<el-tooltip class="item" effect="dark" content="请注意,ID的修改可能会导致该组件相关事件失效!" placement="left">
<el-input class="input" v-model="props.id" @change="handlerChangeId" ></el-input>
</el-tooltip>
</el-form-item>
<el-form-item label="标题">
<el-input class="input" v-model="props.label"></el-input>
</el-form-item>
<el-form-item label="栅格">
<el-input-number v-model="props.span" :min="1" :max="24"/>
</el-form-item>
<el-form-item label="宽度">
<el-input-number v-model="props.width" :min="0" :max="100"/>%
</el-form-item>
<el-form-item label="提示符">
<el-input class="input" v-model="props.placeholder" placeholder="请输入提示符"/>
</el-form-item>
<!-- <el-form-item label="表单栅格">
<el-slider class="input" v-model="props.span" :max="24" :min="1" :marks="{12:''}"></el-slider>
</el-form-item> -->
<el-form-item label="栅格间隔">
<el-input-number v-model="props.gutter" :min="0"></el-input-number>
</el-form-item>
<el-form-item label="标签宽度">
<el-input-number v-model="props.labelWidth" :min="0" :max="200"></el-input-number>
</el-form-item>
<el-form-item label="显示标签">
<el-switch v-model="props.showLabel" @change="handlerChangeLabel"></el-switch>
</el-form-item>
<el-form-item label="大小">
<el-radio-group v-model="props.size">
<el-radio-button label="medium">正常</el-radio-button>
<el-radio-button label="small">略小</el-radio-button>
<el-radio-button label="mini">迷你</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item label="清除">
<el-switch v-model="props.clearable"></el-switch>
</el-form-item>
<el-form-item label="禁用">
<el-switch v-model="props.disabled" ></el-switch>
</el-form-item>
<el-form-item label="完整路径">
<el-switch v-model="props.props['show-all-levels']" ></el-switch>
</el-form-item>
<el-form-item label="分隔符">
<el-input v-model="props.props.separator" ></el-input>
</el-form-item>
<el-form-item label="搜索">
<el-switch v-model="props.props.filterable" ></el-switch>
</el-form-item>
<el-form-item label="展开方式">
<el-radio-group v-model="props.props.props.expandTrigger">
<el-radio-button label="click">点击</el-radio-button>
<el-radio-button label="hover">悬停</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item label="多选">
<el-switch v-model="props.props.props.multiple"></el-switch>
</el-form-item>
<el-form-item label="任一级可选">
<el-switch v-model="props.props.props.checkStrictly"></el-switch>
</el-form-item>
<el-form-item label="数据类型">
<el-radio-group v-model="props.dataType" @change="handlerChangeDataType">
<el-radio-button label="static">静态数据</el-radio-button>
<el-radio-button label="dynamic">动态数据</el-radio-button>
</el-radio-group>
</el-form-item>
<div v-show="props.dataType ==='dynamic'">
<el-form-item label="地址">
<el-input v-model="props.action"></el-input>
</el-form-item>
<el-form-item label="显示标识">
<el-input v-model="props.props.props.label"></el-input>
</el-form-item>
<el-form-item label="值标识">
<el-input v-model="props.props.props.value"></el-input>
</el-form-item>
<el-form-item label="下级标识">
<el-input v-model="props.props.props.children"></el-input>
</el-form-item>
</div>
<div v-show="props.dataType ==='static'">
<el-form-item label="静态数据">
<el-button icon="el-icon-edit-outline" circle @click="handlerStaticData"></el-button>
</el-form-item>
<el-form-item label="省市区">
<el-checkbox v-model="props['china-area-data']" @change="handlerSetAreaData"/>
</el-form-item>
</div>
<!-- <el-form-item label="URL">
<el-input v-model="props.action"></el-input>
</el-form-item> -->
<el-dialog :visible.sync="staticDataVisible" width="70%"
:close-on-press-escape="false"
:close-on-click-modal="false"
:show-close="false"
:center="true"
top="20px"
>
<codemirror v-model="staticOptions" :options="codeMirror"/>
<span slot="footer" class="dialog-footer">
<el-button type="primary" @click="handlerSave">确 定</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import {changeId} from '../mixin'
//引入 省市区 数据
import {areaData} from '../../utils/chinaAreaData';
import {codemirror} from 'vue-codemirror';
// 核心样式
import 'codemirror/lib/codemirror.css';
// 引入主题后还需要在 options 中指定主题才会生效
import 'codemirror/theme/dracula.css';
import 'codemirror/mode/javascript/javascript'
const options = {
tabSize: 2, // 缩进格式
theme: 'dracula', // 主题,对应主题库 JS 需要提前引入
lineNumbers: true, // 显示行号
line: true,
styleActiveLine: true, // 高亮选中行
hintOptions: {
completeSingle: true // 当匹配只有一项的时候是否自动补全
}
}
/**
* input的配置项
*/
export default {
name:"cascaderConfig",
props:['props'],
components:{
codemirror
},
mixins:[changeId],
data(){
return {
staticDataVisible:false,
codeMirror:options,
staticOptions:'',
tempOptions:[]
}
},
methods:{
handlerChangeLabel(val){
this.props.labelWidth = val?'80':'1'
},
handlerStaticData(){
this.staticOptions = JSON.stringify(this.props.options,null,4);
this.staticDataVisible = true;
},
handlerSave(){
this.props.options = JSON.parse(this.staticOptions);
this.staticDataVisible = false;
},
handlerChangeDataType(value){
if(value === 'static'){
this.props.options = [];
this.props.options = this.tempOptions;
}else{
this.tempOptions = this.props.options;
this.props.options = [];
}
},
handlerSetAreaData(val){
if(val){
const areaoptions = areaData();
this.tempOptions = this.props.options;
this.props.options = areaoptions;
}else{
this.props.options = this.tempOptions;
}
}
},
mounted(){
},
watch:{
}
}
</script>
<style scoped>
</style>
\ No newline at end of file
<template>
<div v-show="props.compType === 'checkbox'">
<!-- <el-form-item label="字段名">
<el-input class="input" v-model="props"></el-input>
</el-form-item> -->
<el-form-item label="ID">
<el-tooltip class="item" effect="dark" content="请注意,ID的修改可能会导致该组件相关事件失效!" placement="left">
<el-input class="input" v-model="props.id" @change="handlerChangeId"></el-input>
</el-tooltip>
</el-form-item>
<el-form-item label="标题">
<el-input class="input" v-model="props.label"></el-input>
</el-form-item>
<el-form-item label="提示符">
<el-input class="input" v-model="props.placeholder" placeholder="请输入提示符"/>
</el-form-item>
<!-- <el-form-item label="表单栅格">
<el-slider class="input" v-model="props.span" :max="24" :min="1" :marks="{12:''}"></el-slider>
</el-form-item> -->
<el-form-item label="栅格间隔">
<el-input-number v-model="props.gutter" :min="0"></el-input-number>
</el-form-item>
<el-form-item label="标签宽度">
<el-input-number v-model="props.labelWidth" :min="1" :max="200"></el-input-number>
</el-form-item>
<el-form-item label="显示标签">
<el-switch v-model="props.showLabel" @change="handlerChangeLabel"></el-switch>
</el-form-item>
<el-form-item label="必填">
<el-switch v-model="props.required"></el-switch>
</el-form-item>
<el-form-item label="垂直">
<el-switch v-model="props.vertical"></el-switch>
</el-form-item>
<el-form-item label="最小数量">
<el-input-number v-model="props.min" :min="1" ></el-input-number>
</el-form-item>
<el-form-item label="最大数量">
<el-input-number v-model="props.max" :min="1" ></el-input-number>
</el-form-item>
<el-form-item label="选项样式">
<el-radio-group v-model="props.optionType">
<el-radio-button label="default">默认</el-radio-button>
<el-radio-button label="button">按钮</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item label="显示边框">
<el-switch v-model="props.border"></el-switch>
</el-form-item>
<el-form-item label="选项尺寸" v-show="props.border||props.optionType ==='button'">
<el-radio-group v-model="props.size">
<el-radio-button label="medium">正常</el-radio-button>
<el-radio-button label="small">略小</el-radio-button>
<el-radio-button label="mini">迷你</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item label="禁用">
<el-switch v-model="props.disabled" @change="handlerChangeDisStatus('disabled')"></el-switch>
</el-form-item>
<el-form-item label="默认值">
<el-input class="input"
:value="setDefaultValue(props.value)"
placeholder="请输入默认值"
@input="onDefaultValueInput"
/>
</el-form-item>
<el-form-item label="数据类型">
<el-radio-group v-model="props.dataType" @change="handlerChangeDataType">
<el-radio-button label="static">静态数据</el-radio-button>
<el-radio-button label="dynamic">动态数据</el-radio-button>
</el-radio-group>
</el-form-item>
<div v-show='props.dataType ==="static"'>
<el-divider>选项</el-divider>
<draggable :list="props.options" handle=".option-drag">
<div v-for="(item, index) in props.options" :key="index" class="select-item">
<div class="select-line-icon option-drag">
<i class="el-icon-s-operation" />
</div>
<el-input v-model="item.label" placeholder="选项名" size="small" />
<el-input
placeholder="选项值"
size="small"
:value="item.value"
@input="setOptionValue(item, $event)"
/>
<div class="close-btn select-line-icon" @click="props.options.splice(index, 1)">
<i class="el-icon-remove-outline" />
</div>
</div>
</draggable>
<div style="margin-left: 20px;">
<el-button
style="padding-bottom: 0"
icon="el-icon-circle-plus-outline"
type="text"
@click="addSelectItem"
>
添加选项
</el-button>
</div>
</div>
<div v-show='props.dataType ==="dynamic"'>
<el-form-item label="地址">
<el-input v-model="props.action"></el-input>
</el-form-item>
</div>
</div>
</template>
<script>
import {changeId} from '../mixin'
import draggable from "vuedraggable";
import { isNumberStr } from '../../utils/index'
/**
* input的配置项
*/
let vm = {
name:"checkboxConfig",
props:['props','getFormId'],
components:{
draggable
},
mixins:[changeId],
data(){
return {
}
},
methods:{
handlerChangeLabel(val){
this.props.labelWidth = val?'80':'1'
},
handlerChangeDisStatus(val){
this.props.readOnly = !val
},
handlerChangeReadStatus(val){
this.props.disabled = !val
},
setDefaultValue(val) {
if (Array.isArray(val)) {
return val.join(',')
}
if (['string', 'number'].indexOf(val) > -1) {
return val
}
if (typeof val === 'boolean') {
return `${val}`
}
return val
},
onDefaultValueInput(str) {
if (Array.isArray(this.props.value)) {
// 数组
this.$set(
this.props,
'value',
str.split(',').map(val => (isNumberStr(val) ? +val : val))
)
} else if (['true', 'false'].indexOf(str) > -1) {
// 布尔
this.$set(this.props, 'value', JSON.parse(str))
} else {
// 字符串和数字
this.$set(
this.props,
'value',
isNumberStr(str) ? +str : str
)
}
},
setOptionValue(item,val){
item.value = isNumberStr(val) ? +val : val
},
addSelectItem(){
this.props.options.push({
label: '',
value: ''
})
},
multipleChange(val){
// this.$set(this.props, 'value', val ? [] : '')
},
handlerChangeDataType(value){
if(value === 'static'){
this.props.options = [];
this.props.options = this.tempOptions;
}else{
this.tempOptions = this.props.options;
this.props.options = [];
}
}
},
mounted(){
},
watch: {
}
}
export default vm;
</script>
<style lang="scss" scoped>
.input{
width:75%
}
</style>
\ No newline at end of file
<template>
<div v-show="props.compType === 'colorPicker'">
<el-form-item label="ID">
<el-tooltip class="item" effect="dark" content="请注意,ID的修改可能会导致该组件相关事件失效!" placement="left">
<el-input class="input" v-model="props.id" @change="handlerChangeId" ></el-input>
</el-tooltip>
</el-form-item>
<el-form-item label="显示标签">
<el-switch v-model="props.showLabel" @change="handlerShowLabel"></el-switch>
</el-form-item>
<el-form-item label="标签文字" v-show="props.showLabel">
<el-input class="input" v-model="props.label"></el-input>
</el-form-item>
<el-form-item label="标签长度" v-show="props.showLabel">
<el-input-number v-model="props.labelWidth" :min="1" :max="200"></el-input-number>
</el-form-item>
<el-form-item label="透明">
<el-switch v-model="props['show-alpha']"></el-switch>
</el-form-item>
<el-form-item label="默认颜色">
<el-color-picker v-model="props.value" />
</el-form-item>
<el-form-item label="大小">
<el-radio-group v-model="props.size">
<el-radio-button label="medium">常规</el-radio-button>
<el-radio-button label="small">略小</el-radio-button>
<el-radio-button label="mini">迷你</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item label="预定义颜色">
<div class="select-item" v-for="(item,index) in props.predefine" :key="item">
<span class="el-color-picker__color"><!--style="background-color: rgb(64, 158, 255);"-->
<span class="el-color-picker__color-inner" :style="{'background-color':item}">
</span>
</span>
<div class="close-btn select-line-icon">
<i class="el-icon-remove-outline" @click="handlerRemoveColor(index)"/>
</div>
</div>
<br/>
<el-color-picker v-model="color" @change="handlerAddPreColor"></el-color-picker>
</el-form-item>
</div>
</template>
<script>
import {changeId} from '../mixin'
export default {
name:"buttonConfig",
props:{
props:{}
},
mixins:[changeId],
data(){
return {
color:'#409EFF',
}
},
methods:{
handlerShowLabel(val){
if(val){
this.props.labelWidth = 80;
}else{
this.props.labelWidth = 0;
}
},
handlerAddPreColor(val){
console.log(val);
this.props.predefine.push(val);
console.log(this.props.predefine);
},
handlerRemoveColor(index){
this.props.predefine.splice(index,1);
}
},
mounted(){
}
}
</script>
<style scoped>
.el-color-picker__color{
position: relative;
display: block;
box-sizing: border-box;
border: 1px solid #999;
border-radius: 2px;
width:100px;
height:30px;
float:left;
margin-right:2px;
}
</style>
<template>
<div v-show="props.compType === 'date'">
<el-form-item label="ID">
<el-tooltip class="item" effect="dark" content="请注意,ID的修改可能会导致该组件相关事件失效!" placement="left">
<el-input class="input" v-model="props.id" @change="handlerChangeId"></el-input>
</el-tooltip>
</el-form-item>
<el-form-item label="标题">
<el-input class="input" v-model="props.label"></el-input>
</el-form-item>
<el-form-item label="栅格间隔">
<el-input-number v-model="props.gutter" :min="0"></el-input-number>
</el-form-item>
<el-form-item label="标签宽度">
<el-input-number v-model="props.labelWidth" :min="1" :max="200"></el-input-number>
</el-form-item>
<el-form-item label="显示标签">
<el-switch v-model="props.showLabel"></el-switch>
</el-form-item>
<el-form-item label="提示符">
<el-input class="input" v-model="props.placeholder"></el-input>
</el-form-item>
<el-form-item label="必填">
<el-switch v-model="props.required"></el-switch>
</el-form-item>
<el-form-item label="时间类型">
<el-select class="input" v-model="props.type" @change="handlerFormatChange">
<el-option v-for="item in dateTypeOptions" :key="item.value" :label="item.label" :value="item.value"></el-option>
</el-select>
</el-form-item>
<el-form-item label="时间格式">
<el-input class="input" :value="props.format" @change="handlerChangeValueFormat"/>
</el-form-item>
<el-form-item label="清空">
<el-switch v-model="props.clearable"></el-switch>
</el-form-item>
<el-form-item label="只读">
<el-switch v-model="props.readonly"></el-switch>
</el-form-item>
<el-form-item label="禁用">
<el-switch v-model="props.disabled"></el-switch>
</el-form-item>
<el-form-item label="分隔符" v-show="props.type === 'monthrange'||props.type === 'daterange'||props.type === 'datetimerange'">
<el-input v-model="props['range-separator']"></el-input>
</el-form-item>
<el-form-item label="默认值">
<el-date-picker class="input" v-model="props.value" value-format="yyyy-MM-dd" type="date" placeholder="选择日期"/>
</el-form-item>
</div>
</template>
<script>
import {changeId} from '../mixin'
const dateType =[
{
label: '日(date)',
value: 'date'
},
{
label: '周(week)',
value: 'week'
},
{
label: '月(month)',
value: 'month'
},
{
label: '年(year)',
value: 'year'
},
{
label: '日期时间(datetime)',
value: 'datetime'
},
{
label: '月份范围',
value: 'monthrange'
},
{
label: '日期范围',
value: 'daterange'
},
{
label: '日期时间范围',
value: 'datetimerange'
}
];
const dateTimeFormat = {
date: 'yyyy-MM-dd',
week: 'yyyy 第 WW 周',
month: 'yyyy-MM',
year: 'yyyy',
datetime: 'yyyy-MM-dd HH:mm:ss',
daterange: 'yyyy-MM-dd',
monthrange: 'yyyy-MM',
datetimerange: 'yyyy-MM-dd HH:mm:ss'
}
export default {
name:"inputConfig",
props:['props','getFormId'],
components: {
},
mixins:[changeId],
data(){
return {
dateTypeOptions:dateType
}
},
methods:{
handlerFormatChange(val){
this.props.format = dateTimeFormat[val];
this.props['value-format'] = dateTimeFormat[val];
},
handlerChangeValueFormat(val){
this.props['value-format'] = val;
}
},
mounted(){
}
}
</script>
<style scoped>
.input{
width:75%
}
</style>
<template>
<div v-show="props.compType === 'dialogList'" class="dialogList">
<el-collapse v-model="activePanel" accordion>
<el-collapse-item title="基础设置" name="1">
<el-form-item label="ID" >
<el-tooltip class="item" effect="dark" content="请注意,ID的修改可能会导致该组件相关事件失效!" placement="left">
<el-input class="input" v-model="props.id" ></el-input>
</el-tooltip>
</el-form-item>
<el-form-item label="标题" >
<el-input class="input" v-model="props.label"></el-input>
</el-form-item>
<el-form-item label="栅格" >
<el-input-number v-model="props.span" :min="1" :max="24"/>
</el-form-item>
<el-form-item label="标签宽度">
<el-input-number v-model="props.labelWidth" :min="1" :max="200"></el-input-number>
</el-form-item>
<el-form-item label="显示标签">
<el-switch v-model="props.showLabel"></el-switch>
</el-form-item>
<el-form-item label="必填">
<el-switch v-model="props.required"></el-switch>
</el-form-item>
<el-form-item label="禁用" >
<el-switch v-model="props.disabled"></el-switch>
</el-form-item>
<el-form-item label="默认值" >
<el-input class="input" v-model="props.value"></el-input>
</el-form-item>
<el-form-item label="请求地址">
<el-input v-model="props.action"></el-input>
</el-form-item>
<el-form-item label="标题">
<el-input v-model="props.title"></el-input>
</el-form-item>
<el-form-item label="多选">
<el-switch v-model="props.multi"></el-switch>
</el-form-item>
<el-form-item label="显示序号">
<el-switch v-model="props.showIndex"></el-switch>
</el-form-item>
<el-form-item label="表格高度">
<el-input-number v-model="props.height" :step="10" :max="1500" :min="100"></el-input-number>
</el-form-item>
<el-form-item label="字段值">
<el-input v-model="props.dval"></el-input>
</el-form-item>
<el-form-item label="字段名称">
<el-input v-model="props.dlabel"></el-input>
</el-form-item>
</el-collapse-item>
<el-collapse-item title="字段配置" name="2">
<el-table
:data="colOptions"
@row-dblclick="handlerDeleteRow"
>
<el-table-column property="label" label="字段" align="center" />
<el-table-column property="property" label="属性" align="center" />
<el-table-column property="width" label="宽度" align="center" width="70" />
<el-table-column label="显示">
</el-table-column>
</el-table>
<br/>
<el-alert title="字段和属性不能为空,请检查" v-show="alertShow" type="error" :closable="false"/>
<el-alert title="属性已存在请检查" v-show="propertyExistShow" type="error" :closable="false"/>
<br>
<el-form-item label="字段" label-width="60px">
<el-input v-model="dLabel" />
</el-form-item>
<el-form-item label="属性" label-width="60px">
<el-input v-model="dProperty"/>
</el-form-item>
<el-form-item label="宽度" label-width="60px">
<el-input-number v-model="dWidth" />
</el-form-item>
<el-form-item label="显示" label-width="60px">
<el-switch v-model="dShow" />
</el-form-item>
<div style="margin-left: 20px;">
<el-button
style="padding-bottom: 0"
icon="el-icon-circle-plus-outline"
type="text"
@click="addColItem"
>
添加选项
</el-button>
</div>
</el-collapse-item>
<el-collapse-item title="数值联动" name="3">
</el-collapse-item>
</el-collapse>
</div>
</template>
<script>
/**
* text的配置项
*/
export default {
name:"textConfig",
props:{
props:{}
},
data(){
return {
activePanel:'1',
colOptions:[],
dLabel:'',
dProperty:'',
dWidth:150,
dShow:true,
alertShow:false,
propertyExistShow:false,
}
},
methods:{
addColItem(){
if(this.dLabel!==''&&this.dProperty!==''){
const existOptions = this.colOptions.find(item=>item.property === this.dProperty);
if( typeof existOptions === 'undefined'){
this.alertShow = false;
this.propertyExistShow = false;
const obj = {};
obj.index = this.colOptions.length;
obj.show = this.dShow;
obj.label = this.dLabel;
obj.property = this.dProperty;
obj.width = this.dWidth;
this.colOptions.push(obj);
this.resetFields();
}else{
this.propertyExistShow = true;
}
}else{
this.alertShow = true;
}
},
resetFields(){
this.dLabel = '';
this.dProperty = '';
this.dWidth = 150;
this.dShow = true;
},
handlerDeleteRow(row){
let index = this.colOptions.findIndex(item=>item.property==row.property);
this.colOptions.splice(index,1);
}
},
mounted() {
this.$nextTick(()=> {
this.colOptions = this.colOptions.concat(JSON.parse(this.props.colConf));
})
},
watch:{
'colOptions'(newVal){
this.props.colConf = JSON.stringify(newVal);
}
}
}
</script>
<style scoped>
.dialogList >>> .el-collapse-item__header{
background-color: #f4f6fc;
padding-left:10px;
}
.dialogList >>> .el-collapse-item__header{
height:35px;
}
</style>
\ No newline at end of file
<template>
<div v-show="props.compType === 'divider'">
<el-form-item label="ID">
<el-tooltip class="item" effect="dark" content="请注意,ID的修改可能会导致该组件相关事件失效!" placement="left">
<el-input class="input" v-model="props.id" ></el-input>
</el-tooltip>
</el-form-item>
<el-form-item label="文字">
<el-input class="input" v-model="props.text"></el-input>
</el-form-item>
<el-form-item label="文字大小">
<el-radio-group v-model="props['content-position']">
<el-radio-button label="left"></el-radio-button>
<el-radio-button label="center"></el-radio-button>
<el-radio-button label="right"></el-radio-button>
</el-radio-group>
</el-form-item>
</div>
</template>
<script>
/**
* input的配置项
*/
export default {
name:"dividerConfig",
props:{
props:{}
},
data(){
return {
}
},
methods:{
},
mounted(){
}
}
</script>
<template>
<div v-show="props.compType === 'dynamicTable'">
<el-form-item label="ID">
<el-tooltip class="item" effect="dark" content="请注意,ID的修改可能会导致该组件相关事件失效!" placement="left">
<el-input class="input" v-model="props.id" @change="handlerChangeId"></el-input>
</el-tooltip>
</el-form-item>
<el-form-item label="显示新增按钮" label-width="120px">
<el-switch v-model="props.buttonAdd"></el-switch>
</el-form-item>
<el-form-item label="显示删除按钮" label-width="120px">
<el-switch v-model="props.buttonDel"></el-switch>
</el-form-item>
<el-form-item label="显示行号" label-width="120px">
<el-switch v-model="props.showIndex"></el-switch>
</el-form-item>
<el-form-item label="多选" label-width="120px">
<el-switch v-model="props.multiCheck"></el-switch>
</el-form-item>
<el-form-item label="合计行" label-width="120px">
<el-switch v-model="props['show-summary']"></el-switch>
</el-form-item>
<el-form-item label="合计文本" label-width="120px">
<el-input v-model="props['sum-text']"></el-input>
</el-form-item>
<el-form-item label="单位文本" label-width="120px">
<el-input v-model="props['summary-text']"></el-input>
</el-form-item>
</div>
</template>
<script>
import {changeId} from '../mixin'
export default {
name:"dynamicTableConfig",
props:['props','getFormId'],
mixins:[changeId],
data(){
return {
}
},
methods:{
}
}
</script>
\ No newline at end of file
<template>
<div v-show="props.compType === 'editor'">
<el-form-item label="ID">
<el-tooltip class="item" effect="dark" content="请注意,ID的修改可能会导致该组件相关事件失效!" placement="left">
<el-input class="input" v-model="props.id" @change="handlerChangeId" ></el-input>
</el-tooltip>
</el-form-item>
<el-form-item label="显示标签">
<el-switch v-model="props.showLabel" @change="handlerShowLabel"></el-switch>
</el-form-item>
<el-form-item label="标签文字" v-show="props.showLabel">
<el-input class="input" v-model="props.label"></el-input>
</el-form-item>
<el-form-item label="标签长度" v-show="props.showLabel">
<el-input-number v-model="props.labelWidth" :min="1" :max="200"></el-input-number>
</el-form-item>
<el-form-item label="必填">
<el-switch v-model="props.required"></el-switch>
</el-form-item>
<el-form-item label="验证最大字数">
<el-switch v-model="props.validateMaxText"></el-switch>
</el-form-item>
<el-form-item label="最大字数">
<el-input-number v-model="props.max" :min="100" ></el-input-number>
</el-form-item>
</div>
</template>
<script>
import {changeId} from '../mixin'
export default {
name:"editorConfig",
props:{
props:{}
},
mixins:[changeId],
methods:{
handlerShowLabel(val){
if(val){
this.props.labelWidth = 80;
}else{
this.props.labelWidth = 0;
}
}
}
}
</script>
<!--废弃-->
<template>
<div v-show="props.compType === 'html'">
<!-- <el-form-item label="字段名">
<el-input class="input" v-model="props"></el-input>
</el-form-item> -->
<el-form-item label="ID" labelWidth="40px">
<el-tooltip class="item" effect="dark" content="请注意,ID的修改可能会导致该组件相关事件失效!" placement="left">
<el-input class="input" v-model="props.id" ></el-input>
</el-tooltip>
</el-form-item>
<el-form-item label="文本" labelWidth="40px">
<!-- <el-input type="textarea" class="input" v-model="props.text" rows="12"></el-input> -->
<el-button icon="el-icon-edit-outline" circle @click="handlerEditMore"></el-button>
</el-form-item>
<el-dialog :visible.sync="editTextVisible" width="70%"
:close-on-press-escape="false"
:close-on-click-modal="false"
:show-close="false"
:center="true"
top="20px"
>
<fancy-editor v-model="props.text"/>
<span slot="footer" class="dialog-footer">
<el-button type="primary" @click="handlerSave">确 定</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
/**
* text的配置项
*/
export default{
name:"htmlConfig",
props:{
props:{}
},
data(){
return {
editTextVisible:false
}
},
methods:{
handlerEditMore(){
this.editTextVisible = true;
},
handlerSave(){
this.editTextVisible = false;
}
}
}
</script>
<template>
<div v-show="props.compType === 'input'">
<!-- <el-form-item label="字段名">
<el-input class="input" v-model="props"></el-input>
</el-form-item> -->
<el-form-item label="ID">
<el-tooltip class="item" effect="dark" content="请注意,ID的修改可能会导致该组件相关事件失效!" placement="left">
<el-input class="input" v-model="props.id" @change="handlerChangeId" ></el-input>
</el-tooltip>
</el-form-item>
<el-form-item label="标题">
<el-input class="input" v-model="props.label"></el-input>
</el-form-item>
<el-form-item label="栅格">
<el-input-number v-model="props.span" :min="1" :max="24"/>
</el-form-item>
<!-- <el-form-item label="宽度">-->
<!-- <el-input-number v-model="props.width" :min="1" :max="100"/>%-->
<!-- </el-form-item>-->
<el-form-item label="提示符">
<el-input class="input" v-model="props.placeholder" placeholder="请输入提示符"/>
</el-form-item>
<el-form-item label="栅格间隔">
<el-input-number v-model="props.gutter" :min="0"></el-input-number>
</el-form-item>
<el-form-item label="标签宽度">
<el-input-number v-model="props.labelWidth" :min="1" :max="200"></el-input-number>
</el-form-item>
<el-form-item label="显示标签">
<el-switch v-model="props.showLabel" @change="handlerChangeLabel"></el-switch>
</el-form-item>
<el-form-item label="必填">
<el-switch v-model="props.required"></el-switch>
</el-form-item>
<el-form-item label="清除">
<el-switch v-model="props.clearable"></el-switch>
</el-form-item>
<el-form-item label="禁用">
<el-switch v-model="props.disabled"></el-switch>
</el-form-item>
<el-form-item label="只读">
<el-switch v-model="props.readonly"></el-switch>
</el-form-item>
<el-form-item label="前置图标">
<el-input placeholder="请选择图标" readonly v-model="props['prefix-icon']">
<template slot="append" >
<i class="el-icon-picture" style="cursor: pointer;" @click="handlerPrefixSelectIcon"/>
</template>
</el-input>
</el-form-item>
<el-form-item label="后置图标">
<el-input placeholder="请选择图标" readonly v-model="props['suffix-icon']">
<template slot="append" >
<i class="el-icon-picture" style="cursor: pointer;" @click="handlerSuffixSelectIcon"/>
</template>
</el-input>
</el-form-item>
<el-form-item label="前缀">
<el-input v-model="props.prepend">
</el-input>
</el-form-item>
<el-form-item label="后缀">
<el-input v-model="props.append">
</el-input>
</el-form-item>
<el-form-item label="默认值">
<el-input class="input" v-model="props.value"></el-input>
</el-form-item>
<el-divider>校验</el-divider>
<el-form-item label="验证类型">
<el-select v-model="props.rulesType" @change="handlerChangeRulesType">
<el-option label="无" value="default"/>
<el-option label="电话" value="phone"/>
<el-option label="邮箱" value="email"/>
<el-option label="纯数字" value="number"/>
<el-option label="身份证" value="idcard"/>
</el-select>
</el-form-item>
<div v-for="(item, index) in props.rules" :key="index" class="rule-item">
<el-input v-model="item.rule" placeholder="正则" size="small" />
<p/>
<el-input v-model="item.msg" placeholder="自定义提示" size="small" />
<div class="close-btn select-line-icon" @click="props.rules.splice(index, 1)">
<i class="el-icon-remove-outline close-icon" />
</div>
</div>
<div style="margin-left: 20px;">
<el-button
style="padding-bottom: 0"
icon="el-icon-circle-plus-outline"
type="text"
@click="addRuleItem"
>
添加选项
</el-button>
</div>
<icon-dialog v-model="props['suffix-icon']" :visible.sync="iconDialogVisible_suffix"/>
<icon-dialog v-model="props['prefix-icon']" :visible.sync="iconDialogVisible_prefix"/>
</div>
</template>
<script>
import {changeId} from '../mixin'
import iconDialog from '../../iconDialog';
const defaultRules={
'phone':{'rule':'0?(13|14|15|17|18|19)[0-9]{9}','msg':'您输入的电话号码不符合规则'},
'email':{'rule':'\\w[-\\w.+]*@([A-Za-z0-9][-A-Za-z0-9]+\\.)+[A-Za-z]{2,14}','msg':'您输入的邮件地址不符合规则'},
'number':{'rule':'^[0-9]*$','msg':'您输入的内容不符合纯数字规则'},
'idcard':{'rule':'\\d{17}[\\d|x]|\\d{15}','msg':'您输入的身份证号码不符合规则'}
}
/**
* input的配置项
*/
export default {
name:"inputConfig",
props:['props','getFormId'],
components:{
iconDialog
},
mixins:[changeId],
data(){
return {
val:'',
iconDialogVisible_suffix:false,
iconDialogVisible_prefix:false
}
},
methods:{
handlerChangeLabel(val){
this.props.labelWidth = val?'80':'1'
},
handlerSuffixSelectIcon(){
this.iconDialogVisible_suffix = true;
},
handlerPrefixSelectIcon(){
this.iconDialogVisible_prefix = true;
},
addRuleItem(){
this.props.rules.push({
rule: '',
msg: ''
})
},
handlerChangeRulesType(val){
const obj = defaultRules[val];
this.props.rules.push({
rule: obj.rule,
msg: obj.msg
})
}
},
mounted(){
},
watch:{
}
}
</script>
<style scoped>
.input{
width:75%
}
.rule-item{
padding-top: 5px;
padding-bottom: 5px;
}
.close-btn{
text-align: center;
}
.close-icon:hover{
cursor: pointer;
}
.close-btn >>> .el-icon-remove-outline{
color:"red"
}
</style>
\ No newline at end of file
<template>
<div v-show="props.compType === 'inputNumber'">
<el-form-item label="ID">
<el-tooltip class="item" effect="dark" content="请注意,ID的修改可能会导致该组件相关事件失效!" placement="left">
<el-input class="input" v-model="props.id" @change="handlerChangeId"></el-input>
</el-tooltip>
</el-form-item>
<el-form-item label="标题">
<el-input class="input" v-model="props.label"></el-input>
</el-form-item>
<!-- <el-form-item label="表单栅格">
<el-slider class="input" v-model="props.span" :max="24" :min="1" :marks="{12:''}"></el-slider>
</el-form-item> -->
<el-form-item label="栅格间隔">
<el-input-number v-model="props.gutter" :min="0"></el-input-number>
</el-form-item>
<el-form-item label="标签宽度">
<el-input-number v-model="props.labelWidth" :min="1" :max="200"></el-input-number>
</el-form-item>
<el-form-item label="显示标签">
<el-switch v-model="props.showLabel" @change="handlerChangeLabel"></el-switch>
</el-form-item>
<el-form-item label="必填">
<el-switch v-model="props.required"></el-switch>
</el-form-item>
<el-form-item label="最小值">
<el-input-number v-model="props.min"></el-input-number>
</el-form-item>
<el-form-item label="最大值">
<el-input-number v-model="props.max"></el-input-number>
</el-form-item>
<el-form-item label="步长">
<el-input-number v-model="props.step"></el-input-number>
</el-form-item>
<el-form-item label="精度">
<el-input-number v-model="props.precision" :min="0" :max="10"></el-input-number>
</el-form-item>
<el-form-item label="按钮位置">
<el-radio-group v-model="props['controls-position']">
<el-radio-button label="default">默认</el-radio-button>
<el-radio-button label="right">右侧</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item label="禁用">
<el-switch v-model="props.disabled" @change="handlerChangeDisStatus('disabled')"></el-switch>
</el-form-item>
<el-form-item label="默认值">
<el-input class="input" v-model="props.value"></el-input>
</el-form-item>
</div>
</template>
<script>
import {changeId} from '../mixin'
export default {
name:"inputConfig",
props:['props','getFormId'],
components: {
},
mixins:[changeId],
data(){
return {
}
},
methods:{
handlerChangeLabel(val){
this.props.labelWidth = val?'80':'1'
},
handlerChangeDisStatus(val){
this.props.readOnly = val?false:true
},
handlerChangeReadStatus(val){
this.props.disabled = val?false:true
},
},
mounted(){
}
}
</script>
<style scoped>
.input{
width:75%
}
</style>
\ No newline at end of file
<template>
<div v-show="props.compType === 'link'">
<!-- <el-form-item label="字段名">
<el-input class="input" v-model="props"></el-input>
</el-form-item> -->
<el-form-item label="ID">
<el-tooltip class="item" effect="dark" content="请注意,ID的修改可能会导致该组件相关事件失效!" placement="left">
<el-input class="input" v-model="props.id" @change="handlerChangeId" ></el-input>
</el-tooltip>
</el-form-item>
<el-form-item label="链接文字">
<el-input class="input" v-model="props.text"></el-input>
</el-form-item>
<el-form-item label="类型" >
<el-select v-model="props.type" placeholder="请选择">
<el-option label="primary" value="primary"/>
<el-option label="success" value="success"/>
<el-option label="warning" value="warning"/>
<el-option label="danger" value="danger"/>
<el-option label="info" value="info"/>
</el-select>
</el-form-item>
<el-form-item label="url">
<el-input class="input" v-model="props.href"></el-input>
</el-form-item>
<el-form-item label="禁用">
<el-switch v-model="props.disabled"></el-switch>
</el-form-item>
<el-form-item label="新窗口">
<el-switch v-model="isNewWindow" @change="handlerChangeTargetValue"></el-switch>
</el-form-item>
</div>
</template>
<script>
import {changeId} from '../mixin'
export default {
name:"buttonConfig",
props:{
props:{}
},
components:{
},
mixins:[changeId],
data(){
return {
isNewWindow:true
}
},
methods:{
handlerShowLabel(val){
if(val){
this.props.labelWidth = 80;
}else{
this.props.labelWidth = 0;
}
},
handlerChangeTargetValue(val){
if(val){
this.props.target = '_blank';
}else{
this.props.target = '_self';
}
}
},
mounted(){
}
}
</script>
<template>
<div v-show="props.compType === 'radio'">
<!-- <el-form-item label="字段名">
<el-input class="input" v-model="props"></el-input>
</el-form-item> -->
<el-form-item label="ID">
<el-tooltip class="item" effect="dark" content="请注意,ID的修改可能会导致该组件相关事件失效!" placement="left">
<el-input class="input" v-model="props.id" @change="handlerChangeId"></el-input>
</el-tooltip>
</el-form-item>
<el-form-item label="标题">
<el-input class="input" v-model="props.label"></el-input>
</el-form-item>
<el-form-item label="提示符">
<el-input class="input" v-model="props.placeholder" placeholder="请输入提示符"/>
</el-form-item>
<!-- <el-form-item label="表单栅格">
<el-slider class="input" v-model="props.span" :max="24" :min="1" :marks="{12:''}"></el-slider>
</el-form-item> -->
<el-form-item label="栅格间隔">
<el-input-number v-model="props.gutter" :min="0"></el-input-number>
</el-form-item>
<el-form-item label="标签宽度">
<el-input-number v-model="props.labelWidth" :min="1" :max="200"></el-input-number>
</el-form-item>
<el-form-item label="显示标签">
<el-switch v-model="props.showLabel" @change="handlerChangeLabel"></el-switch>
</el-form-item>
<el-form-item label="必填">
<el-switch v-model="props.required"></el-switch>
</el-form-item>
<el-form-item label="垂直">
<el-switch v-model="props.vertical"></el-switch>
</el-form-item>
<el-form-item label="选项样式">
<el-radio-group v-model="props.optionType">
<el-radio-button label="default">默认</el-radio-button>
<el-radio-button label="button">按钮</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item label="显示边框">
<el-switch v-model="props.border"></el-switch>
</el-form-item>
<el-form-item label="大小" v-show="props.border||props.optionType ==='button'">
<el-radio-group v-model="props.size">
<el-radio-button label="medium">正常</el-radio-button>
<el-radio-button label="small">略小</el-radio-button>
<el-radio-button label="mini">迷你</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item label="禁用">
<el-switch v-model="props.disabled" @change="handlerChangeDisStatus('disabled')"></el-switch>
</el-form-item>
<el-form-item label="默认值">
<el-input class="input"
:value="setDefaultValue(props.value)"
placeholder="请输入默认值"
@input="onDefaultValueInput"
/>
</el-form-item>
<el-form-item label="数据类型">
<el-radio-group v-model="props.dataType" @change="handlerChangeDataType">
<el-radio-button label="static">静态数据</el-radio-button>
<el-radio-button label="dynamic">动态数据</el-radio-button>
</el-radio-group>
</el-form-item>
<div v-show='props.dataType ==="static"'>
<el-divider>选项</el-divider>
<draggable :list="props.options" handle=".option-drag">
<div v-for="(item, index) in props.options" :key="index" class="select-item">
<div class="select-line-icon option-drag">
<i class="el-icon-s-operation" />
</div>
<el-input v-model="item.label" placeholder="选项名" size="small" />
<el-input
placeholder="选项值"
size="small"
:value="item.value"
@input="setOptionValue(item, $event)"
/>
<div class="close-btn select-line-icon" @click="props.options.splice(index, 1)">
<i class="el-icon-remove-outline" />
</div>
</div>
</draggable>
<div style="margin-left: 20px;">
<el-button
style="padding-bottom: 0"
icon="el-icon-circle-plus-outline"
type="text"
@click="addSelectItem"
>
添加选项
</el-button>
</div>
</div>
<div v-show='props.dataType ==="dynamic"'>
<el-form-item label="地址">
<el-input v-model="props.action"></el-input>
</el-form-item>
</div>
</div>
</template>
<script>
import {changeId} from '../mixin'
import draggable from "vuedraggable";
import { isNumberStr } from '../../utils/index'
/**
* input的配置项
*/
let vm = {
name:"inputConfig",
props:['props','getFormId'],
components:{
draggable
},
mixins:[changeId],
data(){
return {
val:123
}
},
methods:{
handlerChangeLabel(val){
this.props.labelWidth = val?'80':'1'
},
handlerChangeDisStatus(val){
this.props.readOnly = !val
},
handlerChangeReadStatus(val){
this.props.disabled = !val
},
setDefaultValue(val) {
if (Array.isArray(val)) {
return val.join(',')
}
if (['string', 'number'].indexOf(val) > -1) {
return val
}
if (typeof val === 'boolean') {
return `${val}`
}
return val
},
onDefaultValueInput(str) {
if (Array.isArray(this.props.value)) {
// 数组
this.$set(
this.props,
'value',
str.split(',').map(val => (isNumberStr(val) ? +val : val))
)
} else if (['true', 'false'].indexOf(str) > -1) {
// 布尔
this.$set(this.props, 'value', JSON.parse(str))
} else {
// 字符串和数字
this.$set(
this.props,
'value',
isNumberStr(str) ? +str : str
)
}
},
setOptionValue(item,val){
item.value = isNumberStr(val) ? +val : val
},
addSelectItem(){
this.props.options.push({
label: '',
value: ''
})
},
multipleChange(val){
// this.$set(this.props, 'value', val ? [] : '')
},
handlerChangeDataType(value){
if(value === 'static'){
this.props.options = [];
this.props.options = this.tempOptions;
}else{
this.tempOptions = this.props.options;
this.props.options = [];
}
}
},
mounted(){
},
watch: {
}
}
export default vm;
</script>
<style lang="scss" scoped>
.input{
width:75%
}
</style>
\ No newline at end of file
<template>
<div v-show="props.compType === 'rate'">
<!-- <el-form-item label="字段名">
<el-input class="input" v-model="props"></el-input>
</el-form-item> -->
<el-form-item label="ID">
<el-tooltip class="item" effect="dark" content="请注意,ID的修改可能会导致该组件相关事件失效!" placement="left">
<el-input class="input" v-model="props.id" @change="handlerChangeId"></el-input>
</el-tooltip>
</el-form-item>
<el-form-item label="标题">
<el-input class="input" v-model="props.label"></el-input>
</el-form-item>
<!-- <el-form-item label="表单栅格">
<el-slider class="input" v-model="props.span" :max="24" :min="1" :marks="{12:''}"></el-slider>
</el-form-item> -->
<el-form-item label="栅格间隔">
<el-input-number v-model="props.gutter" :min="0"></el-input-number>
</el-form-item>
<el-form-item label="标签宽度">
<el-input-number v-model="props.labelWidth" :min="1" :max="200"></el-input-number>
</el-form-item>
<el-form-item label="显示标签">
<el-switch v-model="props.showLabel"></el-switch>
</el-form-item>
<el-form-item label="必填">
<el-switch v-model="props.required"></el-switch>
</el-form-item>
<el-form-item label="允许半选">
<el-switch v-model="props['allow-half']"></el-switch>
</el-form-item>
<el-form-item label="显示分数">
<el-switch v-model="props['show-score']"></el-switch>
</el-form-item>
<el-form-item label="最大值">
<el-input-number v-model="props.max"></el-input-number>
</el-form-item>
<el-form-item label="禁用">
<el-switch v-model="props.disabled"></el-switch>
</el-form-item>
<el-form-item label="默认值">
<el-input class="input" v-model="props.value"></el-input>
</el-form-item>
</div>
</template>
<script>
import {changeId} from '../mixin'
export default {
name:"rate",
props:['props','getFormId'],
components: {
},
mixins:[changeId],
data(){
return {
}
},
methods:{
},
mounted(){
}
}
</script>
<style scoped>
.input{
width:75%
}
</style>
\ No newline at end of file
<!--后期支持flex布局-->
<template>
<div v-show="props.compType === 'row'">
<el-form-item label="栅格间隔">
<el-input-number size="small" v-model="props.gutter" :min="0" :max="100"/>
</el-form-item>
<el-divider>列配置项</el-divider>
<div v-for="(item, index) in props.columns" :key="index" class="select-item">
<div class="select-line-icon">
<i class="el-icon-s-operation" />
</div>
<el-input-number
size="normal"
v-model="item.span"
:min="1" :max="24"
/>
<div class="close-btn select-line-icon" @click="props.columns.splice(index,1)">
<i class="el-icon-remove-outline" />
</div>
</div>
<div style="margin-left: 30px;">
<el-button
style="padding-bottom: 0"
icon="el-icon-circle-plus-outline"
type="text"
@click="handlerAddCol"
>
添加选项
</el-button>
</div>
</div>
</template>
<script>
export default {
name:"rowConfig",
props:['props','getFormId'],
data(){
return {
}
},
methods:{
handlerAddCol(){
const colIndex = this.props.columns+1;
this.props.columns.push({
index:colIndex,
span:12,
list:[]
})
},
},
mounted(){
}
}
</script>
<template>
<div v-show="props.compType === 'select'">
<!-- <el-form-item label="字段名">
<el-input class="input" v-model="props"></el-input>
</el-form-item> -->
<el-form-item label="ID">
<el-tooltip class="item" effect="dark" content="请注意,ID的修改可能会导致该组件相关事件失效!" placement="left">
<el-input class="input" v-model="props.id" @change="handlerChangeId"></el-input>
</el-tooltip>
</el-form-item>
<el-form-item label="标题">
<el-input class="input" v-model="props.label"></el-input>
</el-form-item>
<el-form-item label="提示符">
<el-input class="input" v-model="props.placeholder" placeholder="请输入提示符"/>
</el-form-item>
<!-- <el-form-item label="表单栅格">
<el-slider class="input" v-model="props.span" :max="24" :min="1" :marks="{12:''}"></el-slider>
</el-form-item> -->
<el-form-item label="栅格间隔">
<el-input-number v-model="props.gutter" :min="0"></el-input-number>
</el-form-item>
<el-form-item label="标签宽度">
<el-input-number v-model="props.labelWidth" :min="1" :max="200"></el-input-number>
</el-form-item>
<el-form-item label="显示标签">
<el-switch v-model="props.showLabel" @change="handlerChangeLabel"></el-switch>
</el-form-item>
<el-form-item label="必填">
<el-switch v-model="props.required"></el-switch>
</el-form-item>
<el-form-item label="清除">
<el-switch v-model="props.clearable"></el-switch>
</el-form-item>
<el-form-item label="禁用">
<el-switch v-model="props.disabled"></el-switch>
</el-form-item>
<el-form-item label="多选">
<el-switch v-model="props.multiple" @change="multipleChange"></el-switch>
</el-form-item>
<el-form-item label="折叠" v-show="props.multiple">
<el-switch v-model="props['collapse-tags']" ></el-switch>
</el-form-item>
<el-form-item label="搜索">
<el-switch v-model="props.filterable"></el-switch>
</el-form-item>
<el-form-item label="默认值">
<el-input class="input"
:value="setValue(props.value)"
placeholder="请输入默认值"
@input="onValueInput"
/>
</el-form-item>
<el-form-item label="数据类型">
<el-radio-group v-model="props.dataType" @change="handlerChangeDataType">
<el-radio-button label="static">静态数据</el-radio-button>
<el-radio-button label="dynamic">动态数据</el-radio-button>
</el-radio-group>
</el-form-item>
<div v-show='props.dataType ==="static"'>
<el-divider>选项</el-divider>
<draggable :list="props.options" handle=".option-drag">
<div v-for="(item, index) in props.options" :key="index" class="select-item">
<div class="select-line-icon option-drag">
<i class="el-icon-s-operation" />
</div>
<el-input v-model="item.label" placeholder="选项名" size="small" />
<el-input
placeholder="选项值"
size="small"
:value="item.value"
@input="setOptionValue(item, $event)"
/>
<div class="close-btn select-line-icon" @click="props.options.splice(index, 1)">
<i class="el-icon-remove-outline" />
</div>
</div>
</draggable>
<div style="margin-left: 20px;">
<el-button
style="padding-bottom: 0"
icon="el-icon-circle-plus-outline"
type="text"
@click="addSelectItem"
>
添加选项
</el-button>
</div>
</div>
<div v-show='props.dataType ==="dynamic"'>
<el-form-item label="地址">
<el-input v-model="props.action"></el-input>
</el-form-item>
</div>
</div>
</template>
<script>
import {changeId} from '../mixin'
import draggable from "vuedraggable";
import { isNumberStr } from '../../utils/index'
export default {
name:"inputConfig",
props:['props','getFormId'],
components:{
draggable
},
mixins:[changeId],
data(){
return {
tempOptions:[]
}
},
methods:{
handlerChangeLabel(val){
this.props.labelWidth = val?'80':'1'
},
setValue(val) {
if (Array.isArray(val)) {
return val.join(',')
}
if (['string', 'number'].indexOf(val) > -1) {
return val
}
if (typeof val === 'boolean') {
return `${val}`
}
return val
},
onValueInput(str) {
if (Array.isArray(this.props.value)) {
// 数组
this.$set(
this.props,
'value',
str.split(',').map(val => (isNumberStr(val) ? +val : val))
)
} else if (['true', 'false'].indexOf(str) > -1) {
// 布尔
this.$set(this.props, 'value', JSON.parse(str))
} else {
// 字符串和数字
this.$set(
this.props,
'value',
isNumberStr(str) ? +str : str
)
}
},
setOptionValue(item,val){
item.value = isNumberStr(val) ? +val : val
},
addSelectItem(){
this.props.options.push({
label: '',
value: ''
})
},
multipleChange(val){
this.$set(this.props, 'value', val ? [] : '')
},
handlerChangeDataType(value){
if(value === 'static'){
this.props.options = [];
this.props.options = this.tempOptions;
}else{
this.tempOptions = this.props.options;
this.props.options = [];
}
}
},
mounted(){
}
}
</script>
<style lang="scss" scoped>
.input{
width:75%
}
</style>
\ No newline at end of file
<template>
<div v-show="props.compType === 'slider'">
<!-- <el-form-item label="字段名">
<el-input class="input" v-model="props"></el-input>
</el-form-item> -->
<el-form-item label="ID">
<el-tooltip class="item" effect="dark" content="请注意,ID的修改可能会导致该组件相关事件失效!" placement="left">
<el-input class="input" v-model="props.id" @change="handlerChangeId"></el-input>
</el-tooltip>
</el-form-item>
<el-form-item label="标题">
<el-input class="input" v-model="props.label"></el-input>
</el-form-item>
<!-- <el-form-item label="表单栅格">
<el-slider class="input" v-model="props.span" :max="24" :min="1" :marks="{12:''}"></el-slider>
</el-form-item> -->
<el-form-item label="栅格间隔">
<el-input-number v-model="props.gutter" :min="0"></el-input-number>
</el-form-item>
<el-form-item label="标签宽度">
<el-input-number v-model="props.labelWidth" :min="1" :max="200"></el-input-number>
</el-form-item>
<el-form-item label="显示标签">
<el-switch v-model="props.showLabel"></el-switch>
</el-form-item>
<el-form-item label="必填">
<el-switch v-model="props.required"></el-switch>
</el-form-item>
<el-form-item label="最小值">
<el-input-number v-model="props.min" :min="0"></el-input-number>
</el-form-item>
<el-form-item label="最大值">
<el-input-number v-model="props.max" placeholder="字符长度"/>
</el-form-item>
<el-form-item label="步长">
<el-input-number v-model="props.step"></el-input-number>
</el-form-item>
<el-form-item label="范围选择">
<el-switch v-model="props.range"></el-switch>
</el-form-item>
<el-form-item label="显示断点">
<el-switch v-model="props['show-stops']"></el-switch>
</el-form-item>
<el-form-item label="显示提示消息">
<el-switch v-model="props['show-tooltip']"></el-switch>
</el-form-item>
<el-form-item label="禁用">
<el-switch v-model="props.disabled"></el-switch>
</el-form-item>
<el-form-item label="默认值">
<el-input class="input" v-model="props.value"></el-input>
</el-form-item>
</div>
</template>
<script>
import {changeId} from '../mixin'
export default {
name:"inputConfig",
props:['props','getFormId'],
components: {
},
mixins:[changeId],
data(){
return {
}
},
methods:{
},
mounted(){
}
}
</script>
<style scoped>
.input{
width:75%
}
</style>
\ No newline at end of file
<template>
<div v-show="props.compType === 'table'">
<el-form-item label="ID" >
<el-tooltip class="item" effect="dark" content="请注意,ID的修改可能会导致该组件相关事件失效!" placement="left">
<el-input class="input" v-model="props.id" @change="handlerChangeId" ></el-input>
</el-tooltip>
</el-form-item>
<el-form-item label="单元格样式">
<el-input class="input" v-model="props.tdStyle"></el-input>
</el-form-item>
<el-form-item label="表格宽度">
<el-inputNumber class="input" :min="0" :max="500" v-model="props.width"></el-inputNumber>
</el-form-item>
<el-form-item label="行高">
<el-inputNumber class="input" :min="0" :max="1500" :step="5" v-model="props.height"></el-inputNumber>
</el-form-item>
</div>
</template>
<script>
import {changeId} from '../mixin'
/**
* input的配置项
*/
export default {
name:"inputConfig",
props:['props','getFormId'],
components:{
},
mixins:[changeId],
data(){
return {
}
},
methods:{
}
}
</script>
<style scoped>
</style>
\ No newline at end of file
<template>
<div v-show="props.compType === 'tdItem'">
<el-form-item label="单元格背景">
<el-color-picker v-model="props.style.background" :predefine="predefineColors"/>
</el-form-item>
<el-form-item label="表格宽度(%)">
<el-inputNumber class="input" :min="0" :max="100" v-model="props.style.width"/>
</el-form-item>
</div>
</template>
<script>
/**
* input的配置项
*/
export default {
name:"tdItemConfig",
props:['props'],
data(){
return {
predefineColors: [
'#F6F6F6'
]
}
},
methods:{
}
}
</script>
\ No newline at end of file
<template>
<div v-show="props.compType === 'text'">
<!-- <el-form-item label="字段名">
<el-input class="input" v-model="props"></el-input>
</el-form-item> -->
<el-form-item label="ID" labelWidth="40px">
<el-tooltip class="item" effect="dark" content="请注意,ID的修改可能会导致该组件相关事件失效!" placement="left">
<el-input class="input" v-model="props.id" @change="handlerChangeId" ></el-input>
</el-tooltip>
</el-form-item>
<el-form-item label="文本" labelWidth="40px">
<el-input type="textarea" class="input" v-model="props.text" rows="12" ></el-input>
</el-form-item>
<el-form-item label="颜色" labelWidth="40px">
<el-color-picker v-model="props.color" />
</el-form-item>
<el-form-item label="布局" labelWidth="40px">
<el-radio-group v-model="props.align">
<el-radio-button label="left"></el-radio-button>
<el-radio-button label="center"></el-radio-button>
<el-radio-button label="right"></el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item label="大小" labelWidth="40px">
<el-input-number v-model="props.size" :min="10" :max="50" @change="handlerChangeSize"></el-input-number>
</el-form-item>
<el-form-item label="加粗" labelWidth="40px">
<el-input-number v-model="props.bold" :min="100" :max="800" :step="100" @change="handlerChangeBold"></el-input-number>
</el-form-item>
</div>
</template>
<script>
import {changeId} from '../mixin'
export default {
name:"textConfig",
props:['props'],
data(){
return{
}
},
mixins:[changeId],
methods:{
handlerChangeSize(val){
this.props.size = val+'';
},
handlerChangeBold(val){
this.props.bold = val+'';
}
}
}
</script>
<template>
<div v-show="props.compType === 'textarea'">
<!-- <el-form-item label="字段名">
<el-input class="input" v-model="props"></el-input>
</el-form-item> -->
<el-form-item label="ID">
<el-tooltip class="item" effect="dark" content="请注意,ID的修改可能会导致该组件相关事件失效!" placement="left">
<el-input class="input" v-model="props.id" @change="handlerChangeId"></el-input>
</el-tooltip>
</el-form-item>
<el-form-item label="标题">
<el-input class="input" v-model="props.label"></el-input>
</el-form-item>
<el-form-item label="提示符">
<el-input class="input" v-model="props.placeholder" placeholder="请输入提示符"/>
</el-form-item>
<!-- <el-form-item label="表单栅格">
<el-slider class="input" v-model="props.span" :max="24" :min="1" :marks="{12:''}"></el-slider>
</el-form-item> -->
<el-form-item label="栅格间隔">
<el-input-number v-model="props.gutter" :min="0"></el-input-number>
</el-form-item>
<el-form-item label="标签宽度">
<el-input-number v-model="props.labelWidth" :min="1" :max="200"></el-input-number>
</el-form-item>
<el-form-item label="显示标签">
<el-switch v-model="props.showLabel" @change="handlerChangeLabel"></el-switch>
</el-form-item>
<el-form-item label="必填">
<el-switch v-model="props.required"></el-switch>
</el-form-item>
<el-form-item label="输入框行数">
<el-input-number v-model="props.rows" :min="0"></el-input-number>
</el-form-item>
<el-form-item label="长度限制">
<el-input-number v-model="props.maxlength" placeholder="字符长度"/>
</el-form-item>
<el-form-item label="输入统计">
<el-switch v-model="props['show-word-limit']"></el-switch>
</el-form-item>
<el-form-item label="禁用">
<el-switch v-model="props.disabled" @change="handlerChangeDisStatus"></el-switch>
</el-form-item>
<el-form-item label="只读">
<el-switch v-model="props.readonly" @change="handlerChangeReadStatus"></el-switch>
</el-form-item>
<el-form-item label="默认值">
<el-input class="input" v-model="props.value"></el-input>
</el-form-item>
</div>
</template>
<script>
import {changeId} from '../mixin'
export default {
name:"inputConfig",
props:['props','getFormId'],
components: {
},
mixins:[changeId],
data(){
return {
}
},
methods:{
handlerChangeLabel(val){
this.props.labelWidth = val?'80':'1'
},
handlerChangeDisStatus(val){
this.props.readOnly = !val
},
handlerChangeReadStatus(val){
this.props.disabled = !val
}
},
mounted(){
}
}
</script>
<style scoped>
.input{
width:75%
}
</style>
\ No newline at end of file
<template>
<div v-show="props.compType === 'time'">
<!-- <el-form-item label="字段名">
<el-input class="input" v-model="props"></el-input>
</el-form-item> -->
<el-form-item label="ID">
<el-tooltip class="item" effect="dark" content="请注意,ID的修改可能会导致该组件相关事件失效!" placement="left">
<el-input class="input" v-model="props.id" @change="handlerChangeId"></el-input>
</el-tooltip>
</el-form-item>
<el-form-item label="标题">
<el-input class="input" v-model="props.label"></el-input>
</el-form-item>
<!-- <el-form-item label="表单栅格">
<el-slider class="input" v-model="props.span" :max="24" :min="1" :marks="{12:''}"></el-slider>
</el-form-item> -->
<el-form-item label="栅格间隔">
<el-input-number v-model="props.gutter" :min="0"></el-input-number>
</el-form-item>
<el-form-item label="标签宽度">
<el-input-number v-model="props.labelWidth" :min="1" :max="200"></el-input-number>
</el-form-item>
<el-form-item label="显示标签">
<el-switch v-model="props.showLabel"></el-switch>
</el-form-item>
<el-form-item label="显示标签">
<el-input class="input" v-model="props.placeholder"></el-input>
</el-form-item>
<el-form-item label="必填">
<el-switch v-model="props.required"></el-switch>
</el-form-item>
<el-form-item label="清空">
<el-switch v-model="props.clearable"></el-switch>
</el-form-item>
<el-form-item label="只读">
<el-switch v-model="props.readonly"></el-switch>
</el-form-item>
<el-form-item label="禁用">
<el-switch v-model="props.disabled"></el-switch>
</el-form-item>
<el-form-item label="范围选择">
<el-switch v-model="props['is-range']"></el-switch>
</el-form-item>
<el-form-item label="分隔符" v-show="props['is-range']">
<el-input v-model="props['range-separator']"></el-input>
</el-form-item>
<el-form-item label="默认值">
<el-time-picker class="input" v-model="props.value" placeholder="选择默认时间"/>
</el-form-item>
</div>
</template>
<script>
import {changeId} from '../mixin'
export default {
name:"timeConfig",
components: {
},
mixins:[changeId],
props:['props','getFormId'],
data(){
return {
}
},
methods:{
},
mounted(){
}
}
</script>
<style scoped>
.input{
width:75%
}
</style>
\ No newline at end of file
<template>
<div v-show="props.compType === 'upload'">
<el-form-item label="ID">
<el-tooltip class="item" effect="dark" content="请注意,ID的修改可能会导致该组件相关事件失效!" placement="left">
<el-input class="input" v-model="props.id" @change="handlerChangeId" ></el-input>
</el-tooltip>
</el-form-item>
<el-form-item label="标题">
<el-input class="input" v-model="props.label"></el-input>
</el-form-item>
<el-form-item label="栅格">
<el-input-number v-model="props.span" :min="1" :max="24"/>
</el-form-item>
<el-form-item label="宽度%">
<el-input-number v-model="props.width" :min="1" :max="100"/>
</el-form-item>
<el-form-item label="提示符">
<el-input class="input" v-model="props.placeholder" placeholder="请输入提示符"/>
</el-form-item>
<!-- <el-form-item label="表单栅格">
<el-slider class="input" v-model="props.span" :max="24" :min="1" :marks="{12:''}"></el-slider>
</el-form-item> -->
<el-form-item label="栅格间隔">
<el-input-number v-model="props.gutter" :min="0"></el-input-number>
</el-form-item>
<el-form-item label="标签宽度">
<el-input-number v-model="props.labelWidth" :min="1" :max="200"></el-input-number>
</el-form-item>
<el-form-item label="显示标签">
<el-switch v-model="props.showLabel" @change="handlerChangeLabel"></el-switch>
</el-form-item>
<el-form-item label="请求地址">
<el-input v-model="props.action"></el-input>
</el-form-item>
<el-form-item label="大小(MB)">
<el-input-number v-model="props.fileSize" :min="1" :max="10000" :step="10"/>
</el-form-item>
<el-form-item label="允许文件类型">
<el-input v-model="props.accept"></el-input>
</el-form-item>
<el-form-item label="必填">
<el-switch v-model="props.required"></el-switch>
</el-form-item>
<el-form-item label="多文件上传">
<el-switch v-model="props.multiple"></el-switch>
</el-form-item>
<el-form-item label="显示文件列表">
<el-switch v-model="props['show-file-list']"></el-switch>
</el-form-item>
<el-form-item label="显示类型">
<el-radio-group v-model="props['list-type']" >
<el-radio-button label="text">普通</el-radio-button>
<!-- <el-radio-button label="picture">照片</el-radio-button> -->
<el-radio-button label="picture-card">照片</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item label="按钮文字">
<el-input v-model="props.buttonText"></el-input>
</el-form-item>
<el-form-item label="显示提示">
<el-switch v-model="props.showTip"></el-switch>
</el-form-item>
<el-form-item label="提示内容" v-show="props.showTip">
<el-input v-model="props.tips" ></el-input>
</el-form-item>
</div>
</template>
<script>
import {changeId} from '../mixin'
export default {
name:"uploadConfig",
props:['props'],
components:{
},
mixins:[changeId],
data(){
return {
}
},
methods:{
handlerChangeLabel(val){
this.props.labelWidth = val?'80':'1'
}
},
mounted(){
},
watch:{
}
}
</script>
<style scoped>
.input{
width:75%
}
</style>
\ No newline at end of file
/**
* 表单配置
*/
const formConf = {
version:'1.10',
formRef: 'elForm',
formModel: 'form',
rules: 'rules',
size: 'medium',
labelPosition: 'right',
labelWidth: 80,
formRules: 'rules',
gutter: 15,
disabled: false,
dynamicTableAllowed:true
};
export default formConf;
//动态表单允许放入的组件
export const dynamicTableAllowedItems = [
'input',
'select',
'radio',
'checkbox',
'Switch',
'inputNumber',
'textarea',
'slider',
'rate',
'date',
'time'
];
//row允许放入的items
export const rowAllowedItems = [
'input',
'input',
'select',
'radio',
'checkbox',
'Switch',
'inputNumber',
'textarea',
'slider',
'rate',
'date',
'time'
]
//table允许放入的items
export const tableAllowedItems = [
'row','dynamicTable'
]
\ No newline at end of file
//初始化data里面的数据(1、默认为空,2、之前存在的数据。。)
let itemDatas = {}
export function datas(){
itemDatas = {};
let self = this;
this.itemList.forEach(val => {
if(val.layout === 'rowItem'){ //row布局
dataResolveRowItem(val); //解析row布局
}else if(val.layout === 'dynamicItem'){ //动态表单布局
let obj =dataResolveDynamicItem(val);
let array = [];
array.push(obj);
itemDatas[val.id] = array;
}else if(val.layout === 'tableItem'){ //表格布局
dataResolveTableItem(val);
}else{ //表单
dataResolveColItem(val);
}
})
Object.keys(itemDatas).forEach(key =>{
this.$set(this.form, key, itemDatas[key]);
})
}
function dataResolveRowItem(val){
const columns = val.columns;
columns.forEach(v =>{
v.list.forEach(item =>{
if(item.layout==='dynamicItem'){
let obj =dataResolveDynamicItem(item);
let array = [];
array.push(obj);
itemDatas[item.id] = array;
}else{
dataResolveColItem(item);
}
})
})
}
function dataResolveDynamicItem(val){
const columns = val.columns;
let obj ={};
columns.forEach(v =>{
const key = v.id;
obj[key] = v.value;
})
return obj;
}
/*
遍历表格实现组件渲染
*/
function dataResolveTableItem(val){
val.layoutArray.map((tr)=>{
tr.map((td)=>{
td.columns.map(item=>dataResolveColItem(item));
})
})
}
function dataResolveColItem(val){
itemDatas[val.id] = val.value;
}
export function fillDatas(jsonValue){
const self = this;
Object.keys(jsonValue).forEach(key =>{
if(typeof(self.form[key]) === 'string'||typeof(self.form[key]) === 'number'){
self.$set(self.form, key,jsonValue[key]);
}else if(self.form[key] instanceof Array){//有可能是多选或者是明细表
//判断是否数组中为对象
if(jsonValue[key].length>0){
const firsValue = jsonValue[key][0];//获取第一个对象判断是什么类型
if(typeof(firsValue) === 'string'||typeof(firsValue) === 'number'){
self.$set(self.form, key,jsonValue[key]);
}else{ //明细表数组
const arrayData = jsonValue[key];
//self.form[key] = [];
arrayData.forEach((v,index)=>{
const newV = JSON.parse(JSON.stringify(v));
self.$set(self.form[key],index,newV);
})
}
}
}
})
//console.log(this.form);
}
export function addRow(element){
let obj =dataResolveDynamicItem(element);
this.form[element.id].push(obj);
}
export function deleteRow(scope,element){
this.form[element.id].splice(scope.$index,1);
}
export function batchDeleteRow(indexs,element){
for(let i =0;i<indexs.length;i++){
const index = indexs[i];
this.form[element.id].splice(index,1);
}
}
import {input} from "./items/input";
import {select} from "./items/select";
import {radio} from "./items/radio";
import {checkbox} from "./items/checkbox";
import {Switch} from "./items/Switch";
import {inputNumber} from "./items/inputNumber";
import {textarea} from "./items/textarea";
import {slider} from "./items/slider";
import {rate} from "./items/rate";
import {date} from "./items/date";
import {time} from "./items/time";
import {editor} from "./items/editor";
import {colorPicker} from "./items/colorPicker";
import {cascader} from "./items/cascader";
import {upload} from "./items/upload";
import {dialogList} from "./items/dialogList";
import {dynamicTable} from "./items/dynamicTable";
import {button} from "./items/button";
import {divider} from "./items/divider";
import {row} from "./items/row";
import {table} from "./items/table";
import {alert} from "./items/alert";
import {link} from "./items/link";
import {text} from "./items/text";
import {barCode} from "./items/barCode";
export const formItems = [
input,select,radio,checkbox,Switch,inputNumber,textarea,slider
,rate,date,time,editor,colorPicker,cascader,upload,dialogList,barCode,dynamicTable
];
export const assistFormItems = [button,divider,alert,link,text];
export const layoutFormItems = [row,table];
/**
* 开关,switch是js关键字,所以s大写,避过
*/
export let Switch = {
id:'',
_id:'',
compType: 'Switch',
ele: 'el-switch',
//控件名称(左侧显示)
compName:'开关',
label: '开关',
//图标
compIcon:'switch',
//展示表单的模式
viewType:'component',
//暂时默认为true,无法更改,后期考虑某些时候无法配置
config: true,
// 控件左侧label内容
showLabel:true,
//栅格间隔
gutter:15,
labelWidth: '80',
value: false,
rules:[],
span: 24,
disabled: false,
required: false,
'active-color': '#409EFF',
'inactive-color': '#DCDFE6',
'active-value': 'true',
'inactive-value': 'false'
}
\ No newline at end of file
/**
* 警告
*/
export let alert = {
id:'',
_id:'',
compType: 'alert',
ele: 'el-alert',
compName:'警告',
compIcon:'alert',
//展示表单的模式
viewType:'component',
config: true,
form:false, //是否表单组件
// 控件左侧label内容
showLabel:false,
labelWidth: '0',
span:24,
//标题
title:'alert',
//主题
type:'success',
//辅助文字
description:'form-designer',
//是否可关闭
closable:true,
//是否居中
center:false,
//关闭的按钮
'close-text':'',
//是否显示图标
'show-icon':false,
//主题 light/dark
effect:'light'
}
/**
* 警告
*/
export let barCode = {
id:'',
_id:'',
compType: 'barCode',
ele: 'fancy-bar-code',
compName:'条码',
compIcon:'barcode',
//展示表单的模式
viewType:'component',
config: true,
form:true, //是否表单组件
// 控件左侧label内容
showLabel:false,
labelWidth: '0',
label:'条形码',
span:24,
value:'formDesigner',
format:'CODE128',
lineColor:'#000',
background:'#fff',
width:5,
height:30,
fontSize:12,
displayValue:true
}
\ No newline at end of file
/**
* 单行&多行输入框
*/
export let button = {
id:'',
_id:'',
compType: 'button',
ele: 'el-button',
//控件名称(左侧显示)
compName:'按钮',
//图标
compIcon:'button',
//展示表单的模式
viewType:'component',
//暂时默认为true,无法更改,后期考虑某些时候无法配置
config: true,
// 控件左侧label内容
showLabel:false,
label: '单行文本',
labelWidth: 0,
//是否可以禁用
disabled:false,
//大小,medium / small / mini
size:'medium',
//primary / success / warning / danger / info / text
type:'primary',
span:24,
text:'按钮',
//简单
plain:false,
//圆角
round:false,
//圆形
circle:false,
//加载中
loading:false,
//禁用
disabled:false,
//图标
icon:'',
}
/**
* 级联选择器
*/
export let cascader = {
id:'',
_id:'',
compType: 'cascader',
ele: 'el-cascader',
//控件名称(左侧显示)
compName:'级联选择器',
//图标
compIcon:'cascader',
//展示表单的模式
viewType:'component',
// 是否可配置
//暂时默认为true,无法更改,后期考虑某些时候无法配置
config: true,
// 控件左侧label内容
showLabel:true,
label: '级联选择',
labelWidth: '80',
placeholder: '请选择',
//栅格间隔
gutter:15,
//默认栅格
span:24,
value: [],
//大小
size:"medium",
//禁用
disabled:false,
//数据类型 static,dynamic
dataType:'static',
'china-area-data':false,
//请求地址
action:'https://www.fastmock.site/mock/51715c0157535b99010bde55f2df33c8/formDesigner/api/cascaderOptions',
props:{
//清空
clearable:true,
//分隔符
separator:"/",
//显示完整路径
'show-all-levels':false,
filterable:false,
props: {
//触发方式,hover
expandTrigger:'click',
//多选
multiple:false,
//可选任一级
checkStrictly:false,
label: 'label',
value: 'value',
children: 'children'
}
},
options:[
{
value: 'zhinan',
label: '指南',
children: [{
value: 'shejiyuanze',
label: '设计原则',
children: [{
value: 'yizhi',
label: '一致'
}]
}]
}
]
}
\ No newline at end of file
// export default (_self, h) => {
// return [
// h("Input", {})
// ];
// };
export let checkbox = {
id:'',
_id:'',
compType: 'checkbox',
//控件名称
compName:'复选框',
//element标签
ele: 'el-checkbox-group',
//图标
compIcon:'checkbox',
//展示表单的模式
viewType:'component',
// 是否可配置
config: true,
// 控件左侧label内容
label: '复选框',
placeholder: '请选择',
// 最大长度
maxLength: 50,
//表单栅格
span:24,
//栅格间隔
gutter:'15',
//标签宽度
labelWidth:80,
//显示标签
showLabel:true,
//必填
required:false,
//禁用
disabled:false,
//是否有边框
border:false,
//选项是否垂直
vertical:false,
//选项大小
size:'medium',
//是否是按钮
optionType:'default',
//选项列表
options:[{
label: '选项一',
value: 1
}, {
label: '选项二',
value: 2
}],
//数据类型 static,dynamic
dataType:'static',
//默认渲染的数据
action:'https://www.fastmock.site/mock/51715c0157535b99010bde55f2df33c8/formDesigner/api/options',
value: [],
rules:[],
// 验证错误提示信息
ruleError: '该字段不能为空'
}
/**
* 单行&多行输入框
*/
export let colorPicker = {
id:'',
_id:'',
compType: 'colorPicker',
ele: 'el-color-picker',
//控件名称(左侧显示)
compName:'颜色选择器',
//图标
compIcon:'colorpicker',
//展示表单的模式
viewType:'component',
//暂时默认为true,无法更改,后期考虑某些时候无法配置
config: true,
// 控件左侧label内容
showLabel:false,
label: '单行文本',
labelWidth: 0,
//是否可以禁用
disabled:false,
//大小,medium / small / mini
size:'medium',
//primary / success / warning / danger / info / text
type:'primary',
span:24,
//选择透明度
'show-alpha':false,
//格式
'color-format':'hex',
//预定义颜色
predefine:[],
value:'#409EFF'
}
\ No newline at end of file
/**
* 单行&多行输入框
*/
export let date = {
id:'',
_id:'',
compType: 'date',
ele: 'el-date-picker',
//控件名称(左侧显示)
compName:'日期',
//图标
compIcon:'date',
//展示表单的模式
viewType:'text',
// 是否可配置
//暂时默认为true,无法更改,后期考虑某些时候无法配置
config: true,
// 控件左侧label内容
showLabel:true,
label: '日期',
labelWidth: '80',
placeholder: '请选择',
// 是否必填
required: false,
// 最大长度
maxLength: 50,
//栅格间隔
gutter:15,
//默认栅格
span:24,
//是否可清空
clearable:true,
disabled:false,
readonly:false,
value: '',
rules:[],
//时间类型
type:'date',
format:'yyyy-MM-dd',
'value-format':'yyyy-MM-dd',
'range-separator':'-',
'start-placeholder':'开始日期',
'end-placeholder':'结束日期'
}
/**
* dialogList
*/
export let dialogList = {
id:'',
_id:'',
compType: 'dialogList',
ele: 'fancy-dialog-list',
//控件名称(左侧显示)
compName:'选择列表',
//图标
compIcon:'dialog',
//展示表单的模式
viewType:'component',
// 是否可配置
//暂时默认为true,无法更改,后期考虑某些时候无法配置
config: true,
// 控件左侧label内容
showLabel:true,
label: '选择列表',
labelWidth: '80',
showLabel: true,
labelWidth: 80,
// 是否必填
required: false,
//栅格间隔
gutter:15,
//默认栅格
span:24,
//禁用
disabled:false,
//标题
title:'请选择',
//多选
multi:false,
//显示序号
showIndex:false,
//请求地址
action:'https://www.fastmock.site/mock/51715c0157535b99010bde55f2df33c8/formDesigner/api/dialogListData',
//字段配置
colConf:'[{"index":0,"label":"姓名","property":"name","width":"250","show":true},{"index":1,"label":"日期","property":"date","width":"150","show":true},{"index":2,"label":"地址","property":"address","width":"","show":true}]',
// //值
dval:'id',
//字段
dlabel:'name',
height:500,
value: ''
}
\ No newline at end of file
/**
* 分割线
*/
export let divider = {
id:'',
_id:'',
compType: 'divider',
ele: 'el-divider',
compName:'分割线',
compIcon:'divider',
//展示表单的模式
viewType:'component',
config: true,
form:false,
//内容坐标 left|center|right
'content-position':'left',
text:'',
// 控件左侧label内容
showLabel:false,
labelWidth: '0'
}
/**
* 动态表单
*/
export let dynamicTable = {
id:'',
_id:'',
compType: 'dynamicTable',
ele: 'dynamic-table',
//控件名称(左侧显示)
compName:'动态表格',
layout:'dynamicItem',
//图标
compIcon:'table',
// 是否可配置
//暂时默认为true,无法更改,后期考虑某些时候无法配置
//显示标签
labelWidth:0,
showLabel:false,
config: true,
//显示新增按钮
buttonAdd:true,
//显示删除按钮
buttonDel:true,
//显示行号
showIndex:true,
visible:true,
multiCheck:false,
//合计行
'show-summary':false,
'sum-text':'合计',
'summary-text':'',
columns:[
]
}
/**
* 富文本编辑器
*/
export let editor = {
id:'',
_id:'',
compType: 'editor',
ele: 'fancy-editor',
compName:'编辑器',
compIcon:'editor',
//展示表单的模式
viewType:'html',
config: true,
form:true,
// 控件左侧label内容
showLabel:true,
labelWidth: '80',
label:'文本编辑器',
value:'',
required:false,
validateMaxText:false,
//最大长度
max:2000,
//自定义rules
customRules:[]
}
\ No newline at end of file
/**废弃 */
/**
* html
*/
export let html = {
id:'',
_id:'',
compType: 'html',
ele: 'fancy-html',
compName:'HTML',
compIcon:'html',
//展示表单的模式
viewType:'component',
config: true,
form:false,
text:'<span style="color:red">html</span>',
// 控件左侧label内容
showLabel:false,
label:'',
labelWidth: '0'
}
/**
* 单行&多行输入框
*/
export let input = {
id:'',
_id:'',
compType: 'input',
ele: 'el-input',
//控件名称(左侧显示)
compName:'单行文本',
//图标
compIcon:'input',
//展示表单的模式
viewType:'text',
// 是否可配置
//暂时默认为true,无法更改,后期考虑某些时候无法配置
config: true,
// 控件左侧label内容
showLabel:true,
label: '单行文本',
labelWidth: '80',
placeholder: '请输入文本',
// 是否必填
required: false,
// 最大长度
maxLength: 50,
//栅格间隔
gutter:15,
//默认栅格
span:24,
//组件长度
width: '100%',
//是否可清空
clearable:true,
disabled:false,
readonly:false,
//状态,正常,只读,禁用
status:'normal',
//前置图标
'prefix-icon':'',
//后置图标
'suffix-icon':'',
value: '',
//验证规则(字符,phone,email,number)
rules:[],
//验证规则
rulesType:'default',
//前缀
prepend:'',
//后缀
append:''
}
/**
* 计数器
*/
export let inputNumber = {
id:'',
_id:'',
compType: 'inputNumber',
ele: 'el-inputNumber',
//控件名称(左侧显示)
compName:'计数器',
label: '计数器',
//图标
compIcon:'inputNumber',
//展示表单的模式
viewType:'text',
//暂时默认为true,无法更改,后期考虑某些时候无法配置
config: true,
// 控件左侧label内容
showLabel:true,
//栅格间隔
gutter:15,
labelWidth: '80',
value: 0,
rules:[],
span: 24,
min: 0,
max: 100,
step: 1,
'step-strictly': false,
precision: 0,
'controls-position': 'default',
disabled: false,
readonly: false,
required: false,
regList: []
}
/**
* 文字链接
*/
export let link = {
id:'',
_id:'',
compType: 'link',
ele: 'el-link',
compName:'文字链接',
compIcon:'link',
//展示表单的模式
viewType:'component',
config: true,
form:false, //是否表单组件
// 控件左侧label内容
showLabel:false,
labelWidth: '0',
span:24,
//主题
type:'primary',
//链接地址
href:'http://www.baidu.com',
//是否下划线
underline:true,
//是否禁用
disabled:false,
text:'链接',
target:'_blank'
}
\ No newline at end of file
// export default (_self, h) => {
// return [
// h("Input", {})
// ];
// };
export let radio = {
id:'',
_id:'',
compType: 'radio',
//控件名称
compName:'单选框',
//element标签
ele: 'el-radio-group',
//图标
compIcon:'radio',
//展示表单的模式
viewType:'component',
// 是否可配置
config: true,
// 控件左侧label内容
label: '单选框',
placeholder: '请选择',
// 最大长度
maxLength: 50,
//表单栅格
span:24,
//栅格间隔
gutter:'15',
//标签宽度
labelWidth:80,
//显示标签
showLabel:true,
//必填
required:false,
//禁用
disabled:false,
//是否有边框
border:false,
//选项是否垂直
vertical:false,
//选项大小
size:'medium',
//是否是按钮
optionType:'default',
//选项列表
options:[{
label: '选项一',
value: 1
}, {
label: '选项二',
value: 2
}],
//数据类型 static,dynamic
dataType:'static',
//默认渲染的数据
action:'https://www.fastmock.site/mock/51715c0157535b99010bde55f2df33c8/formDesigner/api/options',
value: '',
rules:[],
// 验证错误提示信息
ruleError: '该字段不能为空'
}
/**
* 评分
*/
export let rate = {
id:'',
_id:'',
compType: 'rate',
ele: 'el-rate',
//控件名称(左侧显示)
compName:'评分',
label: '评分',
//图标
compIcon:'rate',
//展示表单的模式
viewType:'component',
//暂时默认为true,无法更改,后期考虑某些时候无法配置
config: true,
// 控件左侧label内容
showLabel:true,
//栅格间隔
gutter:15,
labelWidth: '80',
value: 1,
rules:[],
span: 24,
disabled: false,
required: false,
max: 5,
'allow-half': false,
'show-score': false
}
\ No newline at end of file
/**
* 栅格布局
*/
// export default (_self, h) => {
// return [
// h("Input", {})
// ];
// };
export let row = {
id:'',
_id:'',
compType: 'row',
//控件名称
compName:'栅格布局',
//element标签
ele: 'el-row',
//图标
compIcon:'col',
layout:'rowItem',
// 是否可配置
config: true,
//
flex:'default',
justify:'start',
align:'top',
gutter:0,
columns:[
{
index:0,
span:12,
list:[]
},
{
index:1,
span:12,
list:[]
}
],
}
export let select = {
id:'',
_id:'',
compType: 'select',
//控件名称
compName:'下拉框',
//element标签
ele: 'el-select',
//图标
compIcon:'select',
//展示表单的模式
viewType:'component',
// 是否可配置
config: true,
// 控件左侧label内容
label: '下拉框',
placeholder: '请选择',
// 最大长度
maxLength: 50,
//表单栅格
span:24,
//栅格间隔
gutter:'15',
//标签宽度
labelWidth:80,
//显示标签
showLabel:true,
//必填
required:false,
//多选
multiple:false,
'collapse-tags':false,
//禁用
disabled:false,
//搜索
filterable:false,
//选项列表
options:[{
label: '选项一',
value: 1
}, {
label: '选项二',
value: 2
}],
//数据类型 static,dynamic
dataType:'static',
//默认渲染的数据
action:'https://www.fastmock.site/mock/51715c0157535b99010bde55f2df33c8/formDesigner/api/options',
//是否可以清空
clearable:false,
value: '',
rules:[],
// 验证错误提示信息
ruleError: '该字段不能为空'
}
/**
* 单行&多行输入框
*/
export let slider = {
id:'',
_id:'',
compType: 'slider',
ele: 'el-slider',
//控件名称(左侧显示)
compName:'滑块',
label: '滑块',
//图标
compIcon:'slider',
//展示表单的模式
viewType:'component',
//暂时默认为true,无法更改,后期考虑某些时候无法配置
config: true,
// 控件左侧label内容
showLabel:true,
//栅格间隔
gutter:15,
labelWidth: '80',
value: 0,
rules:[],
span: 24,
disabled: false,
required: false,
//最小值
min: 0,
//最大值
max: 20,
//步长
step: 1,
//是否显示断点
'show-stops': true,
//是否显示tooltip
'show-tooltip': true,
//范围选择 1,50
range: false
}
\ No newline at end of file
/**
* 表格布局
*/
import {getDefaultTrs} from '../../table/table'
let trs = getDefaultTrs();
export let table = {
id:'',
_id:'',
compType: 'table',
ele: 'fancy-table',
//控件名称(左侧显示)
compName:'表格布局',
//图标
compIcon:'table_layout',
layout:'tableItem',
// 是否可配置
//暂时默认为true,无法更改,后期考虑某些时候无法配置
config: true,
layoutArray:trs,
//单元格样式
tdStyle:'',
width:100,
height:50
}
\ No newline at end of file
/**
* 文本
*/
export let text = {
id:'',
_id:'',
compType: 'text',
ele: 'fancy-text',
compName:'文本',
compIcon:'text',
//展示表单的模式
viewType:'component',
config: true,
form:false,
show:true,
text:'文本',
align:'left',
color:'#000000',
size:'14',
bold:'400',
// 控件左侧label内容
showLabel:false,
labelWidth: '0'
}
\ No newline at end of file
/**
* 单行&多行输入框
*/
export let textarea = {
id:'',
_id:'',
compType: 'textarea',
ele: 'el-input',
//控件名称(左侧显示)
compName:'多行文本',
//图标
compIcon:'textarea',
//展示表单的模式
viewType:'text',
// 是否可配置
//暂时默认为true,无法更改,后期考虑某些时候无法配置
config: true,
// 控件左侧label内容
showLabel:true,
label: '多行文本',
labelWidth: '80',
placeholder: '请输入文本',
type:'textarea',
// 是否必填
required: false,
// 最大长度
maxlength: 50,
//输入统计
'show-word-limit':false,
//栅格间隔
gutter:15,
//默认栅格
span:24,
//是否可清空
clearable:true,
disabled:false,
readonly:false,
rows:4,
//状态,正常,只读,禁用
status:'normal',
value: '',
rules:[],
// 验证错误提示信息
ruleError: '该字段不能为空'
}
/**
* 单行&多行输入框
*/
export let time = {
id:'',
_id:'',
compType: 'time',
ele: 'el-time-picker',
//控件名称(左侧显示)
compName:'时间',
//图标
compIcon:'time',
//展示表单的模式
viewType:'text',
// 是否可配置
//暂时默认为true,无法更改,后期考虑某些时候无法配置
config: true,
// 控件左侧label内容
showLabel:true,
label: '时间',
labelWidth: '80',
placeholder: '请选择',
// 是否必填
required: false,
// 最大长度
maxLength: 50,
//栅格间隔
gutter:15,
//默认栅格
span:24,
//是否可清空
clearable:true,
disabled:false,
readonly:false,
value: '',
rules:[],
'picker-options': {
selectableRange: '00:00:00-23:59:59'
},
'arrow-control':true,
align:'left',
format: 'HH:mm:ss',
'value-format': 'HH:mm:ss',
'is-range':false,
'range-separator':'-'
}
/**
* 上传组件
*/
export let upload = {
id:'',
_id:'',
compType: 'upload',
ele: 'el-upload',
//控件名称(左侧显示)
compName:'附件',
//图标
compIcon:'att',
//展示表单的模式
viewType:'component',
// 是否可配置
//暂时默认为true,无法更改,后期考虑某些时候无法配置
config: true,
// 控件左侧label内容
showLabel:true,
label: '附件上传',
labelWidth: '80',
//栅格间隔
gutter:15,
//默认栅格
span:24,
// 是否必填
required: false,
//上传地址
action:'https://jsonplaceholder.typicode.com/posts/',
//多选上传
multiple:false,
name:'file',
//显示上传文件列表
'show-file-list':true,
//文件列表类型
'list-type':'text',
value:'',
width:100,
//按钮文字
buttonText:'请上传附件',
//是否显示描述
showTip:false,
//描述内容
tips:'点击按钮上传附件',
//允许文件类型
accept:'.pdf, .doc, .docx, .xls, .xlsx',
//文件大小MB
fileSize:10,
}
// 模态框
export const remoteData = {
methods: {
getRemoteData(){
//动态数据
if(this.conf.dataType === 'dynamic'){
this.$axios.get(this.conf.action).then(res => {
if(this.conf.options.length===0){
this.conf.options = this.conf.options.concat(res.data);
}
})
}
}
}
}
export const changeId = {
methods: {
handlerChangeId(val){
let idArray = this.getFormId(this.props._id);
console.log(idArray);
if(idArray.includes(val)){ //如果存在id相等,则提示
this.$message.error('该ID已经存在,请修改');
this.props.id=this.props._id;
}else{
this.props._id=val;
}
}
}
}
import { isAttr,jsonClone } from '../utils';
import childrenItem from './slot/index';
import {remoteData} from './mixin';
//先修改在这里,后续需要优化
function vModel(self, dataObject) {
dataObject.props.value = self.value;
dataObject.on.input = val => {
self.$emit('input', val)
}
//判断是否为上传组件
if(self.conf.compType === 'upload'){
dataObject.attrs['before-upload'] = file=>{
//非限定后缀不允许上传
const fileName = file.name;
const suffixName = fileName.split('.').pop();
if(!self.conf.accept.includes(suffixName)){
self.$message.error('该后缀文件不允许上传');
return false;
}
const fileSize = file.size;
if(fileSize>dataObject.props.fileSize*1024*1024){
self.$message.error('文件大小超出限制,请检查!');
return false;
}
}
}
}
export default {
render(h) {
let dataObject = {
attrs: {},
props: {},
on: {},
style: {}
}
//远程获取数据
this.getRemoteData();
const confClone = jsonClone(this.conf);
const children = childrenItem(h,confClone);
Object.keys(confClone).forEach(key => {
const val = confClone[key]
if (dataObject[key]) {
dataObject[key] = val
} else if(key ==='width'){
dataObject.style= 'width:'+val;
} else if (!isAttr(key)) {
dataObject.props[key] = val
}else {
if(key !== 'value'){
dataObject.attrs[key] = val
}
}
})
/*调整赋值模式,规避cascader组件赋值props会出现覆盖预制参数的bug */
vModel(this, dataObject);
return h(confClone.ele, dataObject, children)
},
props: ['conf','value'],
mixins:[remoteData]
}
//在此注册组件
const components = [
'input',
'select',
'radio',
'checkbox',
'Switch',
'inputNumber',
'textarea',
'slider',
'rate',
'date',
'time',
'editor',
'colorPicker',
'cascader',
'upload',
'button',
'divider',
'alert',
'link',
'dialogList',
'barCode',
'text',
'html',
'row',
'dynamicTable',
'table',
'tdItem'
];
let comps = [];
for (let i in components) {
const comp = {
name: components[i],
content : null
}
comps.push(comp);
}
export default comps;
\ No newline at end of file
import {isAttr,jsonClone} from '../utils/index';
import childrenItem from './slot/index';
import {remoteData} from './mixin';
function vModel(self, dataObject) {
dataObject.on.input = val => {
self.$emit('input', val)
}
}
export default {
render(h) {
let dataObject = {
attrs: {},
props: {},
on: {},
style: {}
}
//远程获取数据
this.getRemoteData();
const confClone = jsonClone(this.conf);
const children = childrenItem(h,confClone);
Object.keys(confClone).forEach(key => {
const val = confClone[key]
if (dataObject[key]) {
dataObject[key] = val
} else if (!isAttr(key)) {
dataObject.props[key] = val
} else if(key ==='width'){
dataObject.style= 'width:'+val;
}else {
dataObject.attrs[key] = val
}
})
/*调整赋值模式,规避cascader组件赋值props会出现覆盖预制参数的bug */
vModel(this, dataObject);
return h(confClone.ele, dataObject, children)
},
props: ['conf'],
mixins:[remoteData]
}
export default function checkRules(element) {
let r = [];
const _trigger = ['blur','change'];
if(element.required){
r.push({required: true, message: element.label+'不能为空', trigger:_trigger});
}
//判断是否有规则
if(element.rules){
element.rules.forEach(obj=>{
r.push({pattern:new RegExp(obj.rule),message:obj.msg, trigger:_trigger});
});
}
//编辑器最大字数验证
if(typeof element.validateMaxText !== 'undefined'&&element.validateMaxText){
const maxRules = {
max: element.max, message: element.label+'超出最大字数限制', trigger:_trigger
}
r.push(maxRules);
}
return r;
};
\ No newline at end of file
export default {
slot(h,conf) {
return conf.text;
}
}
\ No newline at end of file
export default {
slot(h,conf) {
const list = []
const vertical = conf.vertical?'display:block;':'';
conf.options.forEach(item => {
if (conf.optionType === 'button') list.push(<el-checkbox-button label={item.value}>{item.label}</el-checkbox-button>)
else list.push(<el-checkbox label={item.value} style={vertical} border={conf.border}>{item.label}</el-checkbox>)
})
return list
}
}
\ No newline at end of file
import text from './el-button';
export default text;
\ No newline at end of file
export default {
slot(h,conf) {
const slotText = []
if(conf.prepend!==''){
slotText.push(<template slot="prepend">{conf.prepend}</template>);
}
if(conf.append!==''){
slotText.push(<template slot="append">{conf.append}</template>);
}
return slotText;
}
}
\ No newline at end of file
import text from './el-button';
export default text;
\ No newline at end of file
export default {
slot(h,conf) {
const list = [];
const vertical = conf.vertical?'display:block;':'';
conf.options.forEach(item => {
if (conf.optionType === 'button') list.push(<el-radio-button label={item.value} style="">{item.label}</el-radio-button>)
else list.push(<el-radio label={item.value} style={vertical} border={conf.border}>{item.label}</el-radio>)
})
return list
}
}
\ No newline at end of file
export default {
slot(h,conf) {
const list = []
conf.options.forEach(item => {
list.push(<el-option label={item.label} value={item.value} disabled={item.disabled}></el-option>)
})
return list;
}
}
\ No newline at end of file
export default {
slot(h,conf) {
const list = [];
if (conf['list-type'] === 'picture-card') {
list.push(<i class="el-icon-plus"/>)
} 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.tips}</div>)
}
return list
}
}
\ No newline at end of file
const slots = require.context('./', false, /\.js$/);
const componentChild = {};
slots.keys().forEach(obj=>{
const tag = obj.replace('./','').replace('.js','');
if(tag !=='index'){
componentChild[tag] = slots(obj).default;
}
});
export default function childrenItem(h,confClone) {
let children = [];
const childObjs = componentChild[confClone.ele]
if (childObjs&&childObjs.slot) {
Object.keys(childObjs).forEach(key => {
const childFunc = childObjs[key]
children.push(childFunc(h,confClone))
})
}
return children;
};
\ No newline at end of file
import { isAttr,jsonClone } from '../utils';
import childrenItem from './slot/index';
import {remoteData} from './mixin';
function vModel(self, dataObject) {
dataObject.props.value=self.value;
dataObject.on.input = val => {
self.$emit('input', val)
}
}
export default {
render(h) {
let dataObject = {
attrs: {},
props: {},
on: {},
style: {}
}
//远程获取数据
this.getRemoteData();
const confClone = jsonClone(this.conf);
const children = childrenItem(h,confClone);
Object.keys(confClone).forEach(key => {
const val = confClone[key]
if (dataObject[key]) {
dataObject[key] = val
} else if(key ==='width'){
dataObject.style= 'width:'+val+'%';
} else if (!isAttr(key)) {
dataObject.props[key] = val
} else {
dataObject.attrs[key] = val
}
})
/*调整赋值模式,规避cascader组件赋值props会出现覆盖预制参数的bug */
vModel(this, dataObject);
return h(confClone.ele, dataObject, children)
},
props: ['conf','value'],
mixins:[remoteData]
}
<script>
import draggable from 'vuedraggable'
import render from './custom/render'
import {getSimpleId} from "./utils/IdGenerate";
import {dynamicTableAllowedItems,tableAllowedItems} from "./custom/formConf";
import dynamicTable from './dynamic/dynamicTable'
import dynamicTableItem from './dynamic/dynamicTableItem'
import fancyTable from './table/fancyTable'
import fancyTableItem from './table/fancyTableItem'
/**
* 动态表单允许增加的组件列表
*/
const components = {
itemBtns(h, element,parent) {
const {copyItem,deleteItem} = this.$listeners;
return [
<span class="drawing-item-copy" title="复制" onClick={event => {
copyItem(element,parent); event.stopPropagation();
}}>
<i class="el-icon-copy-document" />
</span>,
<span class="drawing-item-delete" title="删除" onClick={event => {
deleteItem(element,parent); event.stopPropagation();
}}>
<i class="el-icon-delete" />
</span>
]
}
}
const layouts = {
colItem(h, element,parent) {
let className = this.activeItem.id === element.id ? 'drawing-item active-from-item' : 'drawing-item'
let labelWidth = element.labelWidth ? `${element.labelWidth}px` : null
const {onActiveItemChange} = this.$listeners;
return (
<el-col class={className} span={element.span} nativeOnClick={event => { onActiveItemChange(element); event.stopPropagation()}}>
<span class="component-name component-id">{element.id}</span>
<el-form-item label={element.showLabel ? element.label : ''}
label-width={labelWidth}
required={element.required} >
<render key={element.id} conf={element} onInput={ event => {
this.$set(element, 'value', event)
}}
/>
</el-form-item>
{components.itemBtns.apply(this, arguments)}
</el-col>
)
},
rowItem(h, element){
const { onActiveItemChange } = this.$listeners
const className = this.activeItem.id === element.id ? 'drawing-item drawing-row-item active-from-item' : 'drawing-item drawing-row-item'
return (
<el-col class={className} >
<el-row gutter={element.gutter} nativeOnClick={event => { onActiveItemChange(element); event.stopPropagation()}}>
<span class="component-name">{element.id}</span>
<div class="drag-wrapper" style="padding-left: 7.5px; padding-right: 7.5px;">
{
element.columns.map((item,index) =>{
return (
<el-col class="drag-col-wrapper" span={item.span}>
<draggable class="drag-wrapper row-drag" v-model={item.list} animation="100" group="componentsGroup"
onAdd={(e)=>{this.handlerAdd(e,item,element)}}
>
{
item.list.map((obj,objIndex)=>{
return renderChildren.call(this,h,obj,element)
})
}
</draggable>
</el-col>
)
})
}
</div>
</el-row>
{components.itemBtns.call(this,h,element)}
</el-col>
)
},
tableItem(h, element){
let className = "";
className = this.activeItem.id === element.id ? 'drawing-item drawing-row-item active-from-item' : 'drawing-item drawing-row-item'
const {onActiveItemChange} = this.$listeners;
return (
<el-col class={className} nativeOnClick={event => { onActiveItemChange(element); event.stopPropagation()}}>
<span class="component-name" style="margin-bottom:15px">{element.id}</span>
<fancy-table layoutArray={element.layoutArray}
tdStyle={element.tdStyle}
width={element.width}
height={element.height}
onSelectItem={(item)=>{onActiveItemChange(item);}}
scopedSlots={{
default: (item) => {
return (
<draggable tag="div" class="table__content row-drag"
v-model={item.td.columns} animation="100"
group="componentsGroup"
onAdd={(e) => {this.handlerTableAdd(e, item.td);e.stopPropagation()}}
>
{
item.td.columns.map((obj)=>{
return renderChildren.call(this,h,obj,item.td)
})
}
</draggable>
);
}
}}
/>
{components.itemBtns.call(this,h,element)}
</el-col>
)
},
dynamicItem(h,element){
let className = "";
className = this.activeItem.id === element.id ? className+'drawing-item active-from-item' : className+'drawing-item'
const {onActiveItemChange} = this.$listeners;
return (
<el-col class={className} >
<dynamic-table conf={element} activeItem={this.activeItem} nativeOnClick={event => { onActiveItemChange(element); event.stopPropagation()}}>
<draggable tag="div" class="dynamic-table__content row-drag" ghost-class="dynamicGhost" v-model={element.columns} animation="100"
group="componentsGroup"
onAdd={(e)=>{this.handlerDynamicAdd(e,element)}}
>
{
element.columns.map((item,index)=>{
return (
<dynamic-table-item item={item} activeItem={this.activeItem}
onSelectItem={(evt,item)=>{onActiveItemChange(item);evt.stopPropagation()}}
onCopyItem={(evt)=>{this.handlerCopyItem(evt,element,index);evt.stopPropagation()}}
onDeleteItem={(evt)=>{this.handlerDeleteItem(evt,element,index);evt.stopPropagation()}}
/>
)
})
}
</draggable>
</dynamic-table>
{components.itemBtns.call(this,h,element)}
</el-col>
)
}
}
/**
* 生成row的子选项
*/
function renderChildren(h, element,parent) {
const layout = layouts[element.layout]
if (layout) {
return layout.call(this, h, element,parent)
}
return layoutIsNotFound.call(this)
}
function layoutIsNotFound() {
throw new Error(`没有与${this.element.layout}匹配的layout`)
}
export default {
name:"designItem",
components: {
render,
draggable,
dynamicTable,
dynamicTableItem,
fancyTable,
fancyTableItem
},
props: {
model: {
type: Object,
default:{}
},
activeItem: {
type: Object,
default:{}
}
},
data(){
return {
activeComponent:this.activeItem
}
},
render(h) {
const layout = layouts[this.model.layout]
if (layout) {
return layout.call(this, h, this.model)
}
return layoutIsNotFound.call(this)
},
methods:{
handlerAdd(evt,item,row){
if(evt.pullMode === 'clone'){
if(!(evt.to.className.indexOf('row-drag')>-1&&this.activeItem.compType==='row')){
item.list.splice(evt.newIndex,0,this.activeItem);
}
}else{
if(evt.item.className.indexOf('el-row')>-1){ //防止row嵌套
const newIndex = evt.newIndex;
const oldIndex = evt.oldIndex;
const rowItem = item.list[newIndex];
item.list.splice(newIndex,1);
this.$message.error('布局组件不允许被嵌套!');
this.$emit('rowItemRollBack',rowItem,oldIndex); //还原到原先的列表中
return false;
}
}
},
/**
* 动态表单
*/
handlerDynamicAdd(evt,item){
if(evt.pullMode === 'clone'){
if(dynamicTableAllowedItems.includes(this.activeItem.compType)){
item.columns.splice(evt.newIndex,0,this.activeItem);
}else{
this.$message.error('该组件不允许被放入动态表格内!');
}
}else{
if(evt.item.className.indexOf('el-row')>-1){ //防止row嵌套
const newIndex = evt.newIndex;
const oldIndex = evt.oldIndex;
const rowItem = item.columns[newIndex];
item.columns.splice(newIndex,1);
this.$message.error('布局组件不允许放入动态表格!');
this.$emit('rowItemRollBack',rowItem,oldIndex); //还原到原先的列表中
return false;
}
}
},
handlerTableAdd(evt,td){
if(evt.pullMode === 'clone'){
if(!tableAllowedItems.includes(this.activeItem.compType)){
td.columns.splice(evt.newIndex,0,this.activeItem);
}else{
this.$message.error('该组件不允许被放入表格内!');
}
}
},
handlerCopyItem(evt,element,index){
const item = element.columns[index];
const clone = JSON.parse(JSON.stringify(item))
let uId = "fd_"+getSimpleId();
clone.id = uId;
clone._id = uId;
element.columns.push(clone);
},
handlerDeleteItem(evt,element,index){
element.columns.splice(index,1);
}
}
}
</script>
\ No newline at end of file
<template>
<!--中间面板-->
<div class="center-board" >
<div class="action-bar">
<el-button icon="el-icon-view" type="text" @click="preview">
预览
</el-button>
<el-button icon="el-icon-view" type="text" @click="view">
查看
</el-button>
<el-button icon="el-icon-tickets" type="text" @click="viewJSON">
JSON
</el-button>
<el-button icon="el-icon-s-tools" type="text" @click="setting">
设置
</el-button>
<el-button class="delete-btn" icon="el-icon-delete-solid" type="text" @click="clear">
清空
</el-button>
<el-button icon="el-icon-question" type="text" @click="help">
帮助
</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="list"
:animation="100"
group="componentsGroup"
draggable=".drawing-item"
>
<design-item
v-for="(element,index) in list"
:key="index"
:model="element"
:activeItem="activeItem"
@rowItemRollBack="handlerRollBack"
@onActiveItemChange="handlerActiveItemChange"
@copyItem="handlerItemCopy"
@deleteItem="handlerItemDelete"/>
</draggable>
<div v-show="infoShow" class="empty-info">
<el-empty description="从左侧拖拽添加控件"></el-empty>
</div>
</el-form>
</el-row>
</el-scrollbar>
<config-panel :activeItem="activeItem" :itemList="list"/>
<!-- 设计器配置弹出框 -->
<el-dialog :visible.sync="formConfVisible" width="50%" top="30px" :center="true">
<el-tabs v-model="activeName">
<el-tab-pane label="表单配置" name="formConf">
<el-form ref="formConf" :model="formConf" label-width="100px">
<el-form-item label="表单名">
<el-input class="input" v-model="formConf.formRef"></el-input>
</el-form-item>
<el-form-item label="表单模型">
<el-input class="input" v-model="formConf.formModel"></el-input>
</el-form-item>
<el-form-item label="校验模型">
<el-input class="input" v-model="formConf.formRules"></el-input>
</el-form-item>
<el-form-item label="表单尺寸">
<el-radio-group v-model="formConf.size">
<el-radio-button label="medium">中等</el-radio-button>
<el-radio-button label="small">较小</el-radio-button>
<el-radio-button label="mini">迷你</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item label="标签对齐">
<el-radio-group v-model="formConf.labelPosition">
<el-radio-button label="right">右对齐</el-radio-button>
<el-radio-button label="left">左对齐</el-radio-button>
<el-radio-button label="top">顶部对齐</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item label="标签宽度">
<el-input-number v-model="formConf.labelWidth" :min="60" :max="140"></el-input-number>
</el-form-item>
<el-form-item label="栅格间隔">
<el-input-number v-model="formConf.gutter" :min="0" :max="30"></el-input-number>
</el-form-item>
<el-form-item label="动态表格支持组件高亮显示">
<el-switch v-model="formConfig.dynamicTableAllowed"></el-switch>
</el-form-item>
<el-form-item label="禁用表单">
<el-switch v-model="formConf.disabled"></el-switch>
</el-form-item>
</el-form>
</el-tab-pane>
<!-- <el-tab-pane label="提交前" name="fourth">开发中...</el-tab-pane> -->
</el-tabs>
<span slot="footer" class="dialog-footer">
<el-button type="primary" @click="handlerSaveFormConf">确 定</el-button>
</span>
</el-dialog>
<el-dialog :visible.sync="previewVisible" width="70%" title="预览">
<preview :itemList="itemList" :formConf="formConf" v-if="previewVisible"/>
</el-dialog>
<el-dialog :visible.sync="JSONVisible" width="70%" title="JSON" center :close-on-click-modal="false">
<codemirror v-model="viewCode" :options="options"/>
<span slot="footer" class="dialog-footer">
<el-button type="primary" @click="handlerSetJson()">确 定</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import draggable from "vuedraggable";
import configPanel from './configPanel'
import designItem from './designItem'
import {getSimpleId} from "./utils/IdGenerate";
import { isLayout, isTable, inTable,jsonClone } from "./utils/index";
import formConf from "./custom/formConf";
import preview from "./preview";
import {codemirror} from 'vue-codemirror';
// 核心样式
import 'codemirror/lib/codemirror.css';
// 引入主题后还需要在 options 中指定主题才会生效
import 'codemirror/theme/dracula.css';
import 'codemirror/mode/javascript/javascript'
export default {
name:"designer",
components:{
draggable,
configPanel,
designItem,
preview,
codemirror
},
props:{
list: {
type: Array,
default:[]
},
formConfig:{
type:Object,
default:formConf
}
},
provide(){
return{
getContext:this
}
},
data() {
return {
formConf:formConf,
activeItem:{},
lastActiveItem:{},
formConfVisible:false,
previewVisible:false,
JSONVisible:false,
itemList:[],
activeName:'formConf',
editorCode:'',
viewCode:'',
// 默认配置
options: {
tabSize: 2, // 缩进格式
theme: 'dracula', // 主题,对应主题库 JS 需要提前引入
lineNumbers: true, // 显示行号
line: true,
styleActiveLine: true, // 高亮选中行
hintOptions: {
completeSingle: true // 当匹配只有一项的时候是否自动补全
}
}
}
},
mounted() {
},
methods: {
preview(){
const clone = JSON.parse(JSON.stringify(this.list))
this.itemList = clone;
this.previewVisible= true;
},
viewJSON(){
this.viewCode = this.code;
this.JSONVisible = true;
},
view(){
localStorage.setItem("formValue",this.code);
window.open('#/view');
},
setting(){
this.formConfVisible = true;
},
clear(){
this.$confirm('此操作将清空整个表单,是否继续?').then(() => {
this.$emit('clear');
})
},
help(){
window.open('https://gitee.com/wurong19870715/formDesigner')
},
handlerActiveItemChange(obj){
this.lastActiveItem = this.activeItem;
this.activeItem = obj;
},
handlerItemCopy(origin,parent){
if(isLayout(origin)){ //row
const clone = jsonClone(origin);
const uId = "row_"+getSimpleId();
console.log(uId);
clone.id = uId;
clone._id = uId;
clone.columns.map((column)=>{
let itemList = [];
column.list.map((item)=>{
const cloneitem = jsonClone(item);
const uId = "fd_"+getSimpleId();
cloneitem.id = uId;
cloneitem._id = uId;
itemList.push(cloneitem);
})
column.list = [];
column.list = itemList;
})
this.list.push(clone);
this.handlerActiveItemChange(clone);
}else if(isTable(origin)){ //表格布局
const clone = jsonClone(origin);
const uId = "table_"+getSimpleId();
clone.id = uId;
clone._id = uId;
clone.layoutArray.map((tr)=>{
tr.map(td=>{
let itemList = [];
td.id=getSimpleId();
td.columns.map((item,i)=>{
const cloneitem = jsonClone(item);
const uId = "fd_"+getSimpleId();
cloneitem.id = uId;
cloneitem._id = uId;
itemList.push(cloneitem);
})
td.columns = [];
td.columns = itemList;
});
})
this.list.push(clone);
this.handlerActiveItemChange(clone);
}else{ //如果是普通组件,需要判断他是否再布局组件下。
if(parent){
if (inTable(parent)) { //增加表格组件的支持
if (parent.columns.some(item => item.id === origin.id)) {
const clone = jsonClone(origin);
const uId = "fd_" + getSimpleId();
clone.id = uId;
clone._id = uId;
parent.columns.push(clone);
this.handlerActiveItemChange(clone);
}
} else {
parent.columns.map((column) => {
if (column.list.some(item => item.id === origin.id)) {
const clone = jsonClone(origin);
const uId = "fd_" + getSimpleId();
clone.id = uId;
clone._id = uId;
column.list.push(clone);
this.handlerActiveItemChange(clone);
}
})
}
}else{
const clone = jsonClone(origin);
const uId = "fd_"+getSimpleId();
clone.id = uId;
clone._id = uId;
this.list.push(clone);
this.handlerActiveItemChange(clone);
}
}
},
handlerItemDelete(origin,parent){
if (isLayout(origin) || isTable(origin)){ //如果是布局组件,则直接删除
const index = this.list.findIndex(item=>item.id === origin.id);
this.list.splice(index,1);
}else{ //如果不是布局组件,则先判断是不是再布局内部,如果不是,则直接删除就可以,如果是,则要在布局内部删除
if(parent){
if (inTable(parent)){ //增加表格组件的支持
const colIndex = parent.columns.findIndex(item => item.id === origin.id);
if (colIndex > -1) {
parent.columns.splice(colIndex, 1);
}
}else{
parent.columns.map((column) => {
const colIndex = column.list.findIndex(item => item.id === origin.id);
if (colIndex > -1) {
column.list.splice(colIndex, 1);
}
})
}
}else{
const index = this.list.findIndex(item=>item.id === origin.id);
this.list.splice(index,1);
}
}
},
handlerSaveFormConf(){
this.formConfVisible = false
},
handlerRollBack(rowItem,oldIndex){ //还原
this.list.splice(oldIndex,0,rowItem);
},
handlerSetJson(){
this.$emit('updateJSON',this.viewCode);
this.JSONVisible = false;
}
},
computed:{
infoShow() {
return this.list.length<1;
},
code() {
let json = {};
json.config = this.formConf;
json.list = this.list;
return JSON.stringify(json,null,4);
}
},
watch: {
activeItem (newValue,oldValue) {
this.lastActiveItem = oldValue;
}
}
}
</script>
<style scoped>
.el-rate{
display:inline-block;
}
.center-scrollbar >>> .el-scrollbar__bar.is-horizontal {
display: none;
}
.center-scrollbar >>> .el-scrollbar__wrap{
overflow-x: hidden;
}
.empty-info >>> .el-empty__description p{
color: #ccb1ea;
font-size:16px;
}
.drawing-board >>> .el-radio.is-bordered+.el-radio.is-bordered{
margin-left:0px;
}
.drawing-board >>> .el-checkbox.is-bordered+.el-checkbox.is-bordered{
margin-left:0px;
}
</style>
<style lang="scss">
@import "./style/designer.scss";
</style>
<style>
@import "./style/designer.css";
</style>
\ No newline at end of file
<!--动态表单(设计器)-->
<template>
<div class="dynamic-table">
<slot>
</slot>
</div>
</template>
<script>
export default {
name:'dynamicTable',
props:['conf','activeItem'],
data(){
return {
test1:'',
list:[]
}
},
components:{
},
methods:{
}
}
</script>
<style>
</style>
\ No newline at end of file
<!--动态表单(设计器)-->
<script>
import draggable from "vuedraggable";
import render from '../custom/render'
const colItem = function(h,element){
const { selectItem,copyItem,deleteItem} = this.$listeners
return (
<div class={{'dynamic-table__item':true,'active':this.isHover||this.isActive}}
style="min-width:200px;width: auto;position:relative" onClick={(e)=>{selectItem(e,element)}}
onMouseover={(e)=>{this.isHover = true}}
onMouseleave={(e)=>{this.isHover = false}}
>
<div class="dynamic-table__item_title">
{element.label}
</div>
<div class="dynamic-table__item_body">
<render conf={element}/><span v-show={element.required} style="color:#F56C6C">*</span>
</div>
<span class="dynamic-table-item-copy" title="复制" v-show={this.showbutton} onClick={(e)=>{copyItem(e,element)}}>
<i class="el-icon-copy-document" />
</span>
<span class="dynamic-table-item-delete" title="删除" v-show={this.showbutton} onClick={(e)=>{deleteItem(e,element)}}>
<i class="el-icon-delete" />
</span>
</div>
)
}
export default {
name:'dynamicTableItem',
props:['item','activeItem'],
data(){
return {
isActive:false,
isHover:false,
}
},
components:{
draggable,
render
},
methods:{
handlerCopy(evt){
this.$emit('copy',evt,this.item);
},
handlerDelete(evt){
this.$emit('delete',evt,this.item);
}
},
watch: {
activeItem(newvalue){
this.isActive = newvalue.id === this.item.id?true:false;
}
},
computed:{
showbutton(){
return this.isActive||this.isHover;
}
},
render:function(h){
return colItem.call(this,h,this.item);
}
}
</script>
<style lang="scss" scoped>
$lighterBlue: #409EFF;
.active{
background: #E6F2FF;
}
.dynamic-table-item-copy{
position: absolute;
width: 22px;
height: 22px;
top:0px;
right:30px;
border: 1px solid;
border-radius: 50%;
cursor: pointer;
font-size: 12px;
line-height: 22px;
text-align: center;
color: $lighterBlue;
background: #fff;
z-index:2;
}
.dynamic-table-item-copy:hover{
color: #fff;
background:$lighterBlue;
}
.dynamic-table-item-delete{
position: absolute;
width: 22px;
height: 22px;
top:0px;
right:0px;
border: 1px solid;
border-radius: 50%;
cursor: pointer;
font-size: 12px;
line-height: 22px;
text-align: center;
color: #F56C6C;
background: #fff;
z-index:2;
}
.dynamic-table-item-delete:hover{
color: #fff;
background:#F56C6C;
}
</style>
<!--操作区域,删除和复制,新增、序号,集成在一个文件中-->
<template>
<div class="dynamic-table__item_opt" style="width: 100%;" >
<div class="dynamic-table__item_title">
操作
</div>
<div class="dynamic-table__item_body" style="text-align:center">
<i class="el-icon-document-copy" style="margin:2px"></i>
<i class="el-icon-delete" style="margin:2px"></i>
</div>
</div>
</template>
<script>
export default {
name:'dynamicTableOptButton',
props:['type'],
data(){
return{
}
}
}
</script>
<style scoped>
.dynamic-table__item_opt{
padding-top:5px;
}
</style>
<!--动态表单(设计器)-->
<template>
<div class="fancyDynamicTable">
<el-table
:data="tableData"
:fit="true"
border
:ref="conf.id"
size="mini"
:cell-style="{padding:'5px 0'}"
:header-cell-style="{background:'#F5F7FA'}"
style="width: 100%"
:row-class-name="tableRowClassName"
@selection-change="handlerSelectionChange"
:show-summary="conf['show-summary']"
:summary-method="sumTotal"
>
<el-table-column align="center" type="selection" width="35px" v-if="conf.multiCheck" fixed="left"/>
<el-table-column align="center" type="index" label="序号" width="50px" v-if="conf.showIndex" fixed="left"/>
<el-table-column align="center" :prop="item.id" v-for="(item,index) in conf.columns" :key="index" min-width="240px;">
<template slot="header">
{{tableColumnLabels[index]}}
</template>
<template slot-scope="scope">
<slot name="item" :rowScope="scope" :item="item"></slot>
</template>
</el-table-column>
<el-table-column align="center" label="操作" width="100px" v-if="conf.buttonDel" fixed="right">
<template slot-scope="scope">
<el-form-item label-width="0px" style="margin:10px 3px 15px 3px;" >
<i class="el-icon-delete optIcon" style="" @click="handlerDelete(scope,conf)"></i>
</el-form-item>
</template>
</el-table-column>
</el-table>
<div class="column-buttons">
<i class="el-icon-circle-plus-outline optIcon button-plus" v-if="conf.buttonAdd" @click="handlerAdd(conf)"/>
<i class="el-icon-remove-outline optIcon button-plus " v-if="BachDeleteButtonShow(conf.id)" @click="handlerBachDelete"/>
</div>
</div>
</template>
<script>
export default {
name:'fancyDynamicTable',
props:['data','conf'],
data(){
return {
tableData:this.data,
tableColumns:[],
tableColumnLabels:[],
multipleSelection: [],
componentsMount:false
}
},
mounted(){
this.conf.columns.forEach(element =>{
this.tableColumnLabels.push(element.label);
let tableCol = {};
Object.assign(tableCol,element);
this.tableColumns.push(tableCol);
});
this.componentsMount = true;
},
components:{
},
methods:{
handlerAdd(origin){
this.$emit('addRow',origin);
},
handlerDelete(scope,element){
this.$emit('deleteRow',scope,element);
},
handlerBachDelete(){
this.$confirm('确认删除选中的数据?').then(() => {
const indexs = [];
this.multipleSelection.forEach(item=>indexs.push(item.index));
this.$emit('batchDeleteRow',indexs,this.conf);
})
},
handlerSelectionChange(val) {
this.multipleSelection = val;
},
tableRowClassName(row) {
row.row.index = row.rowIndex;
},
sumTotal(param){
const { columns, data } = param;
const sums = [];
columns.forEach((column, index) => {
if (index === 0) {
sums[index] = this.conf['sum-text'];
return;
}
const values = data.map(item => Number(item[column.property]));
if (!values.every(value => isNaN(value))) {
sums[index] = values.reduce((prev, curr) => {
const value = Number(curr);
if (!isNaN(value)) {
return prev + curr;
} else {
return prev;
}
}, 0);
sums[index] += ' '+this.conf['summary-text'];
} else {
sums[index] = '';
}
});
return sums;
}
},
computed:{
BachDeleteButtonShow(){
return function(id){
if(this.componentsMount){
return this.conf.multiCheck&&this.$refs[id].selection.length>0;
}
}
}
}
}
</script>
<style scoped>
.fancyDynamicTable{
width: 100%;
padding:10px;
}
.column-buttons{
padding:5px 0 5px 0;
text-align: center;
background-color: #f6f6f6;
}
.optIcon{
font-size:18px;
margin-right:5px;
cursor: pointer;
}
.button-plus{
font-size:30px;
margin-right:10px;
}
.button-plus:hover{
color: #000000;
}
</style>
\ No newline at end of file
<script>
import render from '../custom/previewRender'
import checkRules from '../custom/rule';
const layouts = {
colItem(element,value,parent,index) {
const {valChange} = this.$listeners;
let rules = [];
if(element&&element.rules) {
rules = rules.concat(checkRules(element));
return (
<el-form-item label={''}
label-width={'0px'}
prop={parent.id + '.' + index + '.' + element.id}
rules={rules}
>
<render key={element.id} conf={element} value={value} onInput={event => {
this.eleValue = event;
valChange(this.eleParent.id, this.index, element.id, this.eleValue);
}}/>
{element.required ? <span style="color:#F56C6C">*</span> : ''}
</el-form-item>
)
}
}
}
export default {
name:"fancyDynamicTableItem",
components: {
render
},
props: ['model','value','parent','index'],
mounted(){
let __eleConfig = {};
Object.assign(__eleConfig,this.model);
this.eleConfig = __eleConfig;
},
data(){
return {
eleConfig:{},
eleParent:this.parent,
eleValue:this.value
}
},
render() {
return layouts.colItem.call(this,this.eleConfig,this.eleValue,this.eleParent,this.index)
},
watch:{
value(newVal){
this.eleValue=newVal;
}
}
}
</script>
\ No newline at end of file
<script>
import render from '../custom/viewRender'
const layouts = {
colItem(h, element,value) {
element.disabled= true;
let labelWidth = element.labelWidth ? `${element.labelWidth}px` : null
if(element.viewType === 'component'){
return (
<render key={element.id} conf={element} value={value} onInput={ event => {
this.$set(element,'value',event);
}}/>
)
}else if(element.viewType === 'html'){
return (
<fancy-html text={value}/>
)
}else{
return (
<fancy-text text={value} align="center"/>
)
}
}
}
export default {
name:"fancyDynamicTableViewItem",
components: {
render
},
props: ['model','value'],
data(){
return {
eleConfig:this.model
}
},
render(h) {
return layouts.colItem.call(this, h, this.eleConfig,this.value)
}
}
</script>
<style>
/* .el-form-item__label{
font-weight: 600;
} */
</style>
\ No newline at end of file
<!--动态表单(设计器)-->
<template>
<div class="fancyDynamicTable">
<el-table
:data="data"
:fit="true"
border
size="mini"
:cell-style="{padding:'5px 0'}"
:header-cell-style="{background:'#F5F7FA'}"
:show-summary="conf['show-summary']"
:summary-method="sumTotal"
style="width: 100%">
<el-table-column align="center" type="index" label="序号" width="50px" v-if="conf.showIndex" fixed="left"/>
<el-table-column align="center" :prop="item.id" v-for="(item,index) in conf.columns" :key="index" min-width="150px;">
<template slot="header">
{{tableColumnLables[index]}}
</template>
<template slot-scope="scope">
<slot name="item" :rowScope="scope" :item="item"></slot>
</template>
</el-table-column>
</el-table>
</div>
</template>
<script>
export default {
name:'fancyDynamicViewTable',
props:['data','conf'],
data(){
return {
tableColumns:[],
tableColumnLables:[]
}
},
mounted(){
this.conf.columns.forEach(element =>{
this.tableColumnLables.push(element.label);
let tableCol = {};
Object.assign(tableCol,element);
this.tableColumns.push(tableCol);
});
},
methods:{
sumTotal(param){
const { columns, data } = param;
const sums = [];
columns.forEach((column, index) => {
if (index === 0) {
sums[index] = this.conf['sum-text'];
return;
}
const values = data.map(item => Number(item[column.property]));
if (!values.every(value => isNaN(value))) {
sums[index] = values.reduce((prev, curr) => {
const value = Number(curr);
if (!isNaN(value)) {
return prev + curr;
} else {
return prev;
}
}, 0);
sums[index] += ' '+this.conf['summary-text'];
} else {
sums[index] = '';
}
});
return sums;
}
}
}
</script>
<style scoped>
.fancyDynamicTable{
widows: 100%;
padding:10px;
}
.column-buttons{
margin-top:15px;
text-align: center;
}
.optIcon{
font-size:18px;
margin-right:5px;
cursor: pointer;
}
</style>
\ No newline at end of file
<!--文本扩展-->
<template>
<div class="dialog-list">
<el-input v-model="dialogValue" readonly @click.native="handlerShowDialog" :disabled="disabled" style="width:95%" suffix-icon="el-icon-search"></el-input>
<el-dialog
:visible.sync="dialogVisible"
:title="title"
width="60%"
center
:append-to-body="true"
:show-close="true"
:lock-scroll="true"
@open="show()"
:destroy-on-close="true"
top="15px"
>
<!--搜索暂不启用-->
<!-- <div class="search-text" v-show="searchable">
<el-input v-model="searchText" placeholder="请输入筛选内容" size="mini" suffix-icon="el-icon-search" clearable style="width:30%"></el-input>
</div> -->
<el-table
ref="dataTable"
:data="filterGridData"
border
:row-class-name="tableRowClassName"
:row-style="{height: '10px'}"
:cell-style="{padding: '5px 0'}"
:header-cell-style="{
'background-color': '#fafafa',
'border-bottom': '1px #e6f7ff solid'
}"
:highlight-current-row="!multi"
:max-height="height"
@row-dblclick="handlerRowDoubleClick"
@current-change="handleCurrentChange"
@selection-change="handleSelectionChange"
>
<el-table-column type="selection" width="55" v-if="multi"></el-table-column>
<el-table-column type="index" v-if="showIndex" align="center"></el-table-column>
<el-table-column :property="item.property" :label="item.label" :width="item.width" align="center" :key="index" v-for="(item,index) in jsonColConf"/>
</el-table>
<span slot="footer" class="dialog-footer">
<el-button type="primary" @click="handlerSelect">确 定</el-button>
<el-button @click="handlerHideDialog">取 消</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
const splitKey = ";";
export default {
name:"fancyDialogList",
props:{
value: {
type: String,
default:''
},
title:{
type:String,
default:'请选择'
},
multi:{
type:Boolean,
default:false
},
disabled:{
type:Boolean,
default:false
},
showIndex:{ //显示序号
type:Boolean,
default:false
},
action:{
type:String,
default:''
},
height:{
type:Number,
default:600
},
colConf:{
type:String,
default:''
},
dval:{
type:String,
default:'id'
},
dlabel:{
type:String,
default:'name'
}
},
data() {
return {
currentRow: null,
dialogValue:'',
dialogVisible:false,
gridData: []
}
},
mounted(){
this.$nextTick(() => {
this.$axios.get(this.action).then(res => {
this.gridData = [];
this.gridData = this.gridData.concat(res.data.list);
if(this.value !=='' && this.dialogValue ===''){
if(this.multi){
const ids = this.value.split(splitKey);
this.currentRow = [];
ids.forEach(e=>{
const index = this.gridData.findIndex(element=>(element[this.dval]+"") == e);
if(index>0){
const row = this.gridData[index];
this.currentRow.push(row);
}
})
this.dialogValue = this.selectName;
}else{
const index = this.gridData.findIndex(element=>element[this.dval] == this.value);
if(index>0){
const row = this.gridData[index];
this.dialogValue = row[this.dlabel];
}
}
}
})
})
},
methods:{
handlerShowDialog(){
if(this.disabled) return;
this.dialogVisible = true;
},
handleClose(){
},
tableRowClassName(v){
if(v.rowIndex%2 ==1){
return 'odd-row';
}
return '';
},
handleCurrentChange(val) {
if(!this.multi){
this.currentRow = val;
}
},
handlerRowDoubleClick(val){
if(!this.multi){
this.currentRow = val;
this.handlerSelect();
}
},
handleSelectionChange(val){
this.currentRow = val;
},
handlerSelect(){
this.dialogVisible = false;
let dialogVal = '';
let dialogId = '';
dialogVal = this.selectName;
dialogId = this.selectId;
this.dialogValue = dialogVal;
this.$emit('input',dialogId+'');
},
handlerHideDialog(){
this.dialogVisible = false;
this.dialogValue = '';
this.$emit('input','');
},
setDialogValue(){
if(this.multi){
const ids = this.value.split(splitKey);
this.currentRow = [];
ids.forEach(e=>{
const index = this.gridData.findIndex(element=>element[this.dval] == e);
if(index>0){
const row = this.gridData[index];
this.$refs.dataTable.toggleRowSelection(row);
}
})
}else{
const index = this.gridData.findIndex(element=>element[this.dval] == this.value);
const row = this.gridData[index];
this.$refs.dataTable.setCurrentRow(row);
}
},
show(){
this.$nextTick(() => {
this.setDialogValue();
})
}
},
computed:{
jsonColConf(){
return JSON.parse(this.colConf);
},
selectName(){
if(this.currentRow == null){
return '';
}
if(this.multi){
let names = '';
this.currentRow.forEach(element=>{
names = names+splitKey+element[this.dlabel];
})
if(names.length>0){
names = names.substring(1);
}
return names;
}else{
return this.currentRow[this.dlabel];
}
},
selectId(){
if(this.currentRow == null){
return '';
}
if(this.multi){
let ids = '';
this.currentRow.forEach(element=>{
ids = ids+splitKey+element[this.dval];
})
if(ids.length>0){
ids = ids.substring(1);
}
return ids;
}else{
return this.currentRow[this.dval];
}
},
filterGridData(){
return this.gridData;
}
}
}
</script>
<style scoped>
/**#e6f7ff; */
.dialog-list >>>.el-table--enable-row-hover .el-table__body tr:hover>td{
background-color: #d1dfd5
}
.search-text{
margin-bottom: 10px;
}
</style>
<style>
.el-table .odd-row {
background-color:#FAFAFA;
}
</style>
\ No newline at end of file
<template>
<div class="edit_container" :class="{warn_edit_container:warnTextLength}">
<quill-editor
v-model="content"
ref="myQuillEditor"
:options="editorOption"
@blur="onEditorBlur($event)" @focus="onEditorFocus($event)"
@change="onEditorChange($event)">
</quill-editor>
<div class="text_number_tips" :class="{warn_text_number_tips:warnTextLength}">{{currentLength}}/{{maxTextLength}}</div>
</div>
</template>
<script>
import 'quill/dist/quill.core.css'
import 'quill/dist/quill.snow.css'
import 'quill/dist/quill.bubble.css'
import { quillEditor } from 'vue-quill-editor'
export default {
components:{
quillEditor
},
props:{
value:{
type:String,
default:''
},
max:{
type:Number,
default:0
},
validateMaxText:{
type:Boolean,
default:false
},
id:{
type:String,
default:''
}
},
data() {
return {
content: this.value,
currentLength:0,
defaultMaxLength:2000,
editorOption: {}
}
},
methods: {
onEditorBlur(editor){
}, // 失去焦点事件
onEditorFocus(v){
}, // 获得焦点事件
onEditorChange(v){
this.currentLength = v.text.length-1;
this.$emit('input',this.content);
}, // 内容改变事件
},
computed: {
editor() {
return this.$refs.myQuillEditor.quill;
},
maxTextLength(){
let len = this.defaultMaxLength;
if(this.max>=1){
len = this.max;
}
return len;
},
warnTextLength(){
const warn =this.validateMaxText&&this.currentLength>this.maxTextLength;
return warn;
}
},
watch:{
value(newVal){
this.content = newVal;
},
}
}
</script>
<style>
.ql-editor{
height:400px;
}
.edit_container .text_number_tips{
float:right;
margin-top:-30px;
padding-right:10px;
}
.warn_edit_container{
border: solid 1px #F56C6C;
}
.warn_text_number_tips{
color:#F56C6C;
}
</style>
\ No newline at end of file
<!--废弃-->
<!--文本扩展-->
<template>
<div v-if="show">
<p v-html="text"/>
</div>
</template>
<script>
export default {
name:"fancyHtml",
props:{
text: {
type: String,
default:''
},
show:{
type:Boolean,
default:true
}
}
}
</script>
<!--文本扩展-->
<template>
<div v-show="show" class="test">
<p v-html="text" style="margin-block-start:0em;margin-block-end:0em;"
:style="{'text-align':align,
'color':color,
'font-size':size+'px',
'font-weight':bold
}"/>
</div>
</template>
<script>
export default {
name:"fancyText",
props:{
text: {
type: String,
default:''
},
show:{
type:Boolean,
default:true
},
align:{
type:String,
default:'left'
},
color:{
type:String,
default:''
},
size:{
type:Number,
default:14,
},
bold:{
type:Number,
default:400,
}
},
data(){
return {
htmlText:''
}
}
}
</script>
<style>
</style>
<template>
<div >
<el-row :gutter="formConf.gutter" class="form-builder">
<el-form
:rules="rules"
:ref="formConf.formModel"
:size="formConf.size"
:model="form"
:label-position="formConf.labelPosition"
:disabled="formConf.disabled"
:validate-on-rule-change="false"
:label-width="formConf.labelWidth + 'px'"
>
<template v-for="(element,index) in itemList" >
<preview-row-item
v-if="element.compType === 'row'"
:key="'row-'+index"
:model="element"
>
<el-col v-for="(column) in element.columns" :key="column.index" :span="column.span">
<template v-for="(col) in column.list">
<preview-item
v-if="col.compType!== 'dynamicTable'"
:key="col.id"
:model="col"
v-model="form[col.id]"
@valChange="handlerValChange"
/>
<fancy-dynamic-table
v-else-if="col.compType === 'dynamicTable'"
ref="dynamicTable"
:key="'dynamic-'+index"
:data="form[col.id]"
:conf="col"
@addRow="handlerAddRow"
@deleteRow="handlerDeleteRow"
>
<template v-slot:item="{rowScope,item}">
<fancy-dynamic-table-item
:model="item"
:parent="col"
:key="'tableIndex-'+rowScope.$index"
:index="rowScope.$index"
v-model="rowScope.row[item.id]"
@valChange="handlerDynamicValChange"
/>
</template>
</fancy-dynamic-table>
</template>
</el-col>
</preview-row-item>
<fancy-dynamic-table
v-else-if="element.compType === 'dynamicTable'"
:key="'dynamic-'+index"
:data="form[element.id]"
:ref="element.id"
:conf="element"
@addRow="handlerAddRow"
@deleteRow="handlerDeleteRow"
>
<template v-slot:item="{rowScope,item}">
<fancy-dynamic-table-item
:model="item"
:ref="item.id+rowScope.$index"
:parent="element"
:key="'tableIndex-'+rowScope.$index"
:index="rowScope.$index"
v-model="rowScope.row[item.id]"
@valChange="handlerDynamicValChange"
/>
</template>
</fancy-dynamic-table>
<fancy-edit-table
v-else-if="element.compType === 'table'"
:layoutArray="element.layoutArray"
:tdStyle="element.tdStyle"
:width="element.width"
:height="element.height"
>
<template v-slot="{td}">
<template v-for="(col) in td.columns">
<preview-item
v-if="col.compType!== 'dynamicTable'"
:key="col.id"
:model="col"
v-model="form[col.id]"
@valChange="handlerValChange"
/>
</template>
</template>
</fancy-edit-table>
<!--item-->
<el-col class="drag-col-wrapper" :key="index" :span="element.span" v-else>
<preview-item
:model="element"
v-model="form[element.id]"
@valChange="handlerValChange"
/>
</el-col>
</template>
</el-form>
</el-row>
</div>
</template>
<script>
import previewItem from "./previewItem";
import previewRowItem from "./previewRowItem";
import fancyDynamicTable from "./dynamic/fancyDynamicTable";
import fancyDynamicTableItem from "./dynamic/fancyDynamicTableItem";
import {datas,addRow,deleteRow,fillDatas} from "./custom/formDraw";
import fancyEditTable from "./table/fancyEditTable";
export default {
name:'formBuilder',
props:{
value:{
type:String,
default:''
},
buildData:{
type:String,
default:''
},
disabled:{
type:Boolean,
default:false
}
},
components:{
previewItem,
previewRowItem,
fancyDynamicTable,
fancyDynamicTableItem,
fancyEditTable
},
data(){
return{
form:{},
rules:{},
currentIndex:-1
}
},
mounted() {
this.$nextTick(()=> {
if(this.value !==''){
const jsonValue = JSON.parse(this.value)
this.handlerFillDatas(jsonValue);
}
})
},
methods:{
handlerValChange(key,origin){
this.$set(this.form,key,origin);
},
handlerDynamicValChange(parentId,index,key,origin){
this.$set(this.form[parentId][index],key,origin);
this.currentIndex = index;
},
validate(){
this.$refs[this.formConf.formModel].validate((valid) => {
if (valid) {
this.$message.success('success');
this.$emit('input',JSON.stringify(this.form,null,4));
}else{
this.$emit('input','');
}
});
},
handlerAddRow:addRow,
handlerDeleteRow:deleteRow,
handlerInitDatas:datas,
handlerFillDatas:fillDatas
},
created(){
this.handlerInitDatas();
},
computed:{
itemList(){
if(this.buildData!==''){
const buildData = JSON.parse(this.buildData);
return buildData.list;
}else{
return [];
}
},
formConf(){
if(this.buildData!==''){
const buildData = JSON.parse(this.buildData);
buildData.config.disabled = this.disabled;
return buildData.config;
}else{
return {};
}
}
}
}
</script>
<style scoped>
.preview-board{
border: 1px dashed #ccc
}
.form-builder{
padding: 20px;
border:1px solid #dcdfe6;
}
.el-form-item{
margin-left:10px;
margin-right:10px;
}
.form-builder >>> .el-radio.is-bordered+.el-radio.is-bordered{
margin-left:0px;
}
.form-builder >>> .el-checkbox.is-bordered+.el-checkbox.is-bordered{
margin-left:0px;
}
</style>
\ No newline at end of file
<template>
<div class="container">
<div class="left-board">
<div class="d-logo-wrapper">
<div class="d-logo">
Form designer
</div>
</div>
<el-scrollbar class="left-scrollbar">
<!--左侧组件列表-->
<div class="components-list">
<div class="components-title">
常用组件
</div>
<draggable
class="components-draggable"
:list="formItems"
:group="{ name: 'componentsGroup', pull: 'clone', put: false }"
:clone="cloneComponent"
draggable=".components-item"
:sort="false"
@start="onStart"
@end="onEnd"
>
<div
v-for="(element, index) in formItems" :key="index" class="components-item"
@click="addComponent(element)"
>
<div class="components-body" :class="{ 'dynamicTable-tips': dynamicTableExist(element)}">
<icon :code="element.compIcon" :text="element.compName"/>
</div>
</div>
</draggable>
<div class="components-title">
布局组件
</div>
<draggable
class="components-draggable"
:list="layoutFormItems"
:group="{ name: 'componentsGroup', pull: 'clone', put: false }"
:clone="cloneComponent"
draggable=".components-item"
:sort="false"
@start="onStart"
@end="onEnd"
>
<div
v-for="(element, index) in layoutFormItems" :key="index" class="components-item"
@click="addComponent(element)"
>
<div class="components-body">
<icon :code="element.compIcon" :text="element.compName"/>
</div>
</div>
</draggable>
<div class="components-title">
辅助组件
</div>
<draggable
class="components-draggable"
:list="assistFormItems"
:group="{ name: 'componentsGroup', pull: 'clone', put: false }"
:clone="cloneComponent"
draggable=".components-item"
:sort="false"
@start="onStart"
@end="onEnd"
>
<div
v-for="(element, index) in assistFormItems" :key="index" class="components-item"
@click="addComponent(element)"
>
<div class="components-body">
<icon :code="element.compIcon" :text="element.compName"/>
</div>
</div>
</draggable>
</div>
</el-scrollbar>
</div>
<designer ref="designer" :list="designList" :formConfig="formConfig" @clear="designList = []" @updateJSON="handlerUpdateJSON" :activeData="activeData"/>
</div>
</template>
<script>
/**
* 1.0版本
*/
import draggable from "vuedraggable";
import {formItems,assistFormItems,layoutFormItems} from "./custom/itemList";
import designer from "./designer";
import icon from "./icon";
import {getSimpleId,setTableId} from "./utils/IdGenerate";
import formConf from "./custom/formConf";
import {dynamicTableAllowedItems} from "./custom/formConf";
let tempActiveData;
export default {
name:"formDesigner",
components:{
draggable
,icon,
designer
},
data() {
return {
formItems:formItems,
assistFormItems:assistFormItems,
layoutFormItems:layoutFormItems,
designList:[],
activeData:{},
formConfig:formConf
}
},
props:{
value:{
type:String,
default:''
}
},
mounted() {
},
methods: {
addComponent(element){
},
cloneComponent(origin){
const clone = JSON.parse(JSON.stringify(origin))
if (!clone.layout) clone.layout = 'colItem'
if (clone.layout === 'colItem'||clone.layout === 'dynamicItem') {
let uId = "fd_"+getSimpleId();
clone.id = uId;
clone._id = uId;
tempActiveData = clone;
}else if (clone.layout === 'rowItem'){
let uId = "row_"+getSimpleId();
clone.id = uId;
clone._id = uId;
tempActiveData = clone;
}else if(clone.layout === 'tableItem'){
let uId = "table_"+getSimpleId();
clone.id = uId;
clone._id = uId;
//增加td默认的id
setTableId(clone);
tempActiveData = clone;
}
this.$refs.designer.activeItem = tempActiveData;
},
onStart(obj){
},
onEnd(obj){
if(obj.from !== obj.to){
this.activeData = tempActiveData;
this.$refs.designer.activeItem = this.activeData;
if(obj.to.className.indexOf('row-drag')<0){
this.designList.splice(obj.newIndex,0,this.activeData);
}
}else{
this.$refs.designer.activeItem = {};
}
},
getFormData(){
return this.formData;
},
handlerUpdateJSON(json){
const jsonObject = JSON.parse(json);
this.designList = [];
this.designList = this.designList.concat(jsonObject.list);
}
},
computed:{
formData:function(){
const list = this.designList;
const config = this.formConfig;
let formData = {};
formData.list = list;
formData.config = config;
console.log(formData);
return JSON.stringify(formData);
//this.$emit('input',JSON.stringify(formData));
},
dynamicTableExist(){
return function(element){
return this.formConfig.dynamicTableAllowed
&&this.designList.filter(item=>item.compType === 'dynamicTable').length>0
&&dynamicTableAllowedItems.includes(element.compType);
}
}
},
watch:{
value(newVal){
if(newVal !==''){
const formData = JSON.parse(newVal);
this.designList= formData.list;
this.formConfig = formData.config;
}
}
}
}
</script>
<style scoped>
.container{
padding:0px
}
.dynamicTable-tips{
border:1px solid#F08080
}
</style>
\ No newline at end of file
<script>
import render from './custom/viewRender'
const layouts = {
colItem(h, element,value) {
element.disabled= true;
let labelWidth = element.labelWidth ? `${element.labelWidth}px` : null
if(element.viewType === 'component'){
return (
<el-form-item label={element.showLabel ? element.label : ''}
label-width={labelWidth}
prop={element.id}
>
<render key={element.id} conf={element} value={value} onInput={ event => {
this.$set(element,'value',event);
}}/>
</el-form-item>
)
}else if(element.viewType === 'html'){
return (
<el-form-item label={element.showLabel ? element.label : ''}
label-width={labelWidth}
prop={element.id}
>
<fancy-html text={value}/>
</el-form-item>
)
}else{
if(typeof value === 'object'){
value = value[0] + ' ' + element['range-separator'] + ' ' + value[1];
}
return (
<el-form-item label={element.showLabel ? element.label : ''}
label-width={labelWidth}
prop={element.id}
>
{value}
</el-form-item>
)
}
}
}
export default {
name:"formViewItem",
components: {
render
},
props: ['model','value'],
data(){
return {
eleConfig:this.model
}
},
render(h) {
return layouts.colItem.call(this, h, this.eleConfig,this.value)
}
}
</script>
<style>
/* .el-form-item__label{
font-weight: 600;
} */
.el-form-item{
margin-left:10px;
margin-right:10px;
margin-bottom: 5px;
}
</style>
\ No newline at end of file
<!--表单查看页面-->
<template>
<div class="form-viewer">
<el-row :gutter="formConf.gutter" >
<el-form
:ref="formConf.formModel"
:size="formConf.size"
:model="form"
:label-position="formConf.labelPosition"
:disabled="formConf.disabled"
>
<template v-for="(element,index) in itemList" >
<preview-row-item
v-if="element.compType === 'row'"
:key="'row-'+index"
:model="element"
>
<el-col v-for="(column) in element.columns" :key="column.index" :span="column.span">
<form-view-item
v-for="(item) in column.list"
:key="item.id"
:model="item"
v-model="form[item.id]"
/>
</el-col>
</preview-row-item>
<fancy-dynamic-view-table
v-else-if="element.compType === 'dynamicTable'"
:key="'dynamic-'+index"
:data="form[element.id]"
:ref="element.id"
:conf="element"
>
<template v-slot:item="{rowScope,item}">
<fancy-dynamic-table-view-item
:model="item"
:ref="item.id+rowScope.$index"
:parent="element"
:key="'tableIndex-'+rowScope.$index"
:index="rowScope.$index"
v-model="rowScope.row[item.id]"
/>
</template>
</fancy-dynamic-view-table>
<fancy-edit-table
v-else-if="element.compType === 'table'"
:layoutArray="element.layoutArray"
:tdStyle="element.tdStyle"
:width="element.width"
:height="element.height"
>
<template v-slot="{td}">
<form-view-item
v-for="(item) in td.columns"
:key="item.id"
:model="item"
v-model="form[item.id]"
/>
</template>
</fancy-edit-table>
<!--item-->
<el-col class="drag-col-wrapper" :key="index" :span="element.span" v-else>
<form-view-item
:model="element"
v-model="form[element.id]"
/>
</el-col>
</template>
</el-form>
</el-row>
</div>
</template>
<script>
import formViewItem from "./formViewItem";
import previewRowItem from "./previewRowItem";
import fancyDynamicViewTable from "./dynamic/fancyDynamicViewTable";
import fancyDynamicTableViewItem from "./dynamic/fancyDynamicTableViewItem";
import fancyEditTable from "./table/fancyEditTable";
export default {
name:'formViewer',
data(){
return{
}
},
props:{
value:{
type:String,
default:''
},
buildData:{
type:String,
default:''
}
},
components:{
formViewItem,
previewRowItem,
fancyDynamicViewTable,
fancyDynamicTableViewItem,
fancyEditTable
},
mounted() {
this.$nextTick(()=> {
})
},
computed:{
itemList(){
if(this.buildData!==''){
const buildData = JSON.parse(this.buildData);
return buildData.list;
}else{
return [];
}
},
form(){ //转换成json的值
if(this.value!==''){
const value = JSON.parse(this.value);
return value;
}else{
return {};
}
},
formConf(){
if(this.buildData!==''){
const buildData = JSON.parse(this.buildData);
buildData.config.disabled = this.disabled;
return buildData.config;
}else{
return {};
}
}
}
}
</script>
<style scoped>
.preview-board{
border: 1px dashed #ccc
}
.form-viewer{
padding: 20px;
border:1px solid #dcdfe6;
}
.el-form-item{
margin-left:10px;
margin-right:10px;
}
</style>
\ No newline at end of file
/**
* 生成html的核心js函数
*/
let globalConfig
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>`
}
const items = {
'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' : ''
return `<${el.ele} ${vModel} ${placeholder} ${maxlength} ${readonly} ${disabled} ${clearable} />`
},
'textarea':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 type = el.type ? `type="${el.type}"` : ''
return `<${el.ele} ${vModel} ${type} ${placeholder} ${maxlength} ${readonly} ${disabled} ${clearable} />`
}
}
function colWrapper(element,str){
if (element.span) {
return `<el-col :span="${element.span}">
${str}
</el-col>`
}
return str
}
function attrBuilder(el) {
return {
vModel: `v-model="${globalConfig.formModel}.${el.id}"`,
clearable: el.clearable ? 'clearable' : '',
placeholder: el.placeholder ? `placeholder="${el.placeholder}"` : '',
//width: el.style && el.style.width ? ':style="{width: \'100%\'}"' : '',
disabled: el.disabled ? ':disabled=\'true\'' : ''
}
}
const layout = {
colFormItem(element) {
let labelWidth = `label-width="${globalConfig.labelWidth}px"`
let label = `label="${element.label}"`
if (element.labelWidth && element.labelWidth !== globalConfig.labelWidth) {
labelWidth = `label-width="${element.labelWidth}px"`
}
if (element.showLabel === false) {
labelWidth = 'label-width="0"'
label = ''
}
const required = element.required ? 'required' : ''
const itemDom = items[element.compType] ? items[element.compType](element) : null
let str = `<el-form-item ${labelWidth} ${label} ${required}>
${itemDom}
</el-form-item>`
str = colWrapper(element,str);
return str;
}
}
/**
* 生成html源码
* 表单配置和组件列表
*/
export function buildHtmlSource(itemList,formConf){
globalConfig = formConf;
const htmlCode = []
itemList.forEach(el => {
htmlCode.push(layout['colFormItem'](el))
})
const htmlStr = htmlCode.join('\n')
//console.log(htmlStr)
}
\ No newline at end of file
/**
* 生成js的核心js函数
*/
let globalConfig
export function buildJsSource(itemList,formConf){
globalConfig = JSON.parse(JSON.stringify(formConf))
const dataList = []
const optionsList = []
const propsList = []
itemList.forEach(el =>{
buildAttributes(el, dataList, optionsList, propsList)
})
const script = buildexport(
formConf,
dataList.join('\n'),
optionsList.join('\n'),
propsList.join('\n'),
)
globalConfig = null;
console.log(script);
return script;
}
function buildAttributes(el, dataList, optionsList, propsList) {
buildData(el, dataList)
if (el.options && el.options.length) {
buildOptions(el, optionsList)
}
if (el.props && el.props.props) {
buildProps(el, propsList)
}
// if (el.children) {
// el.children.forEach(el2 => {
// buildAttributes(el2, dataList, ruleList, optionsList, methodList, propsList, uploadVarList)
// })
// }
}
function buildData(conf, dataList) {
let value
if (typeof (conf.value) === 'string' && !conf.multiple) {
value = `'${conf.value}'`
} else {
value = `${JSON.stringify(conf.value)}`
}
if(typeof(value) === 'undefined'||value === 'undefined') value = `''`;
console.log(value);
dataList.push(`${conf.id}: ${value},`)
}
function buildOptions(conf, optionsList) {
const str = `${conf.id}Options: ${JSON.stringify(conf.options)},`
optionsList.push(str)
}
function buildProps(conf, propsList) {
const str = `${conf.id}Props: ${JSON.stringify(conf.props.props)},`
propsList.push(str)
}
function buildexport(conf, data, props) {
const str = `export default {
components: {},
props: [],
data () {
return {
${conf.formModel}: {
${data}
}
}
},
computed: {},
watch: {},
created () {},
mounted () {},
}`
return str
}
\ No newline at end of file
<template>
<div class="text">
<svg class="icon" aria-hidden="true">
<use :xlink:href="iconFont"></use>
</svg>
{{text}}
</div>
</template>
<script>
export default {
name:'icon',
props:['code','text'],
computed: {
iconFont(){
return '#icon-'+this.code;
}
}
}
</script>
<style scoped>
.icon{
width:20px;
height:20px;
vertical-align:-5px;
}
</style>
\ No newline at end of file
<!--elementUI 图标选择器-->
<template>
<div >
<el-dialog title="选择icon" width="60%" top="0vh" :visible.sync="dialogVisible">
<ul class="icon-list">
<li v-for="iconName in icons" :key="iconName" @click="handlerSelectIcon(iconName)" :class="{activeIcon:iconName ===value}">
<i :class="iconName"></i>
<!-- <div class="icon-name">{{iconName}}</div> -->
</li>
</ul>
</el-dialog>
</div>
</template>
<script>
import iconList from './utils/icon.json';
export default {
props:{
visible:{
type: Boolean,
default:true
},
value:{
type:String,
default:''
}
},
data(){
return{
icons:iconList,
}
},
methods:{
handlerSelectIcon(iconName){
this.$emit('input',iconName);
this.$emit('update:visible',false);
}
},
computed:{
dialogVisible:{
// getter
get: function () {
return this.visible;
},
// setter
set: function (newValue) {
this.$emit('update:visible',false);
}
}
}
}
</script>
<style scoped>
.icon-list{
padding:0;
margin:0;
font-size:0;
}
.icon-list li{
width: 10%;
height:60px;
font-size:14px;
text-align: center;
list-style-type: none;
overflow: hidden;
padding: 15px 6px 6px 0px;
display: inline-block;
box-sizing: border-box;
}
.icon-list li:hover{
background-color: #F2F6FC;
cursor: pointer;
}
.activeIcon{
background-color: #F2F6FC;
cursor: pointer;
}
.icon-list li i{
width:100%;
font-size: 30px;
padding: 6px 6px 6px 0px;
}
.icon-name{
display: block;
padding-left:6px;
}
.el-dialog {
border-radius: 8px;
margin-bottom: 0;
margin-top: 4vh !important;
display: flex;
flex-direction: column;
max-height: 92vh;
overflow: hidden;
box-sizing: border-box;
}
.el-dialog .el-dialog__header {
padding-top: 14px;
}
.el-dialog .el-dialog__body {
margin: 0 20px 20px 20px;
padding: 0;
overflow: auto;
}
</style>
\ No newline at end of file
import formDesigner from './formDesigner';
import fancyEditor from './extend/fancyEditor';
import fancyHtml from './extend/fancyHtml';
import fancyText from './extend/fancyText';
import fancyBarCode from 'vue-barcode';
import fancyDialogList from './extend/fancyDialogList';
import iconDialog from './iconDialog';
const plugins = {
install : function (Vue) {
Vue.component('form-designer',formDesigner);
Vue.component('fancy-editor',fancyEditor);
Vue.component('fancy-html',fancyHtml);
Vue.component('fancy-text',fancyText);
Vue.component('fancy-bar-code',fancyBarCode);
Vue.component('fancy-dialog-list',fancyDialogList);
Vue.component('icon-dialog',iconDialog);
}
};
// 这一步判断window.Vue是否存在,因为直接引用vue.min.js, 它会把Vue绑到Window上,我们直接引用打包好的js才能正常跑起来。
if (typeof window !== 'undefined' && window.Vue) {
window.Vue.use(plugins);
}
export default plugins;
\ No newline at end of file
<template>
<div class="preview">
<el-row :gutter="formConf.gutter">
<el-form
:rules="rules"
:ref="formConf.formModel"
:size="formConf.size"
:model="form"
:label-position="formConf.labelPosition"
:disabled="formConf.disabled"
:validate-on-rule-change="false"
label-width="formConf.labelWidth + 'px'"
>
<template v-for="(element,index) in list" >
<!-- <el-input v-model="element.id" placeholder=""></el-input> -->
<preview-row-item
v-if="element.compType === 'row'"
:key="'row-'+index"
:model="element"
>
<el-col v-for="(column) in element.columns" :key="column.index" :span="column.span">
<template v-for="(col) in column.list">
<preview-item
v-if="col.compType!== 'dynamicTable'"
:key="col.id"
:model="col"
v-model="form[col.id]"
@valChange="handlerValChange"
/>
<fancy-dynamic-table
v-else-if="col.compType === 'dynamicTable'"
ref="dynamicTable"
:key="'dynamic-'+index"
:data="form[col.id]"
:conf="col"
@addRow="handlerAddRow"
@deleteRow="handlerDeleteRow"
@batchDeleteRow="handlerBatchDeleteRow"
>
<template v-slot:item="{rowScope,item}">
<fancy-dynamic-table-item
:model="item"
:parent="col"
:key="'tableIndex-'+rowScope.$index"
:index="rowScope.$index"
v-model="rowScope.row[item.id]"
@valChange="handlerDynamicValChange"
/>
</template>
</fancy-dynamic-table>
</template>
</el-col>
</preview-row-item>
<fancy-dynamic-table
v-else-if="element.compType === 'dynamicTable'"
:key="'dynamic-'+index"
:data="form[element.id]"
:ref="element.id"
:conf="element"
@addRow="handlerAddRow"
@deleteRow="handlerDeleteRow"
@batchDeleteRow="handlerBatchDeleteRow"
>
<template v-slot:item="{rowScope,item}">
<fancy-dynamic-table-item
:model="item"
:ref="item.id+rowScope.$index"
:parent="element"
:key="'tableIndex-'+rowScope.$index"
:index="rowScope.$index"
v-model="rowScope.row[item.id]"
@valChange="handlerDynamicValChange"
/>
</template>
</fancy-dynamic-table>
<fancy-edit-table
v-else-if="element.compType === 'table'"
:layoutArray="element.layoutArray"
:tdStyle="element.tdStyle"
:width="element.width"
:height="element.height"
>
<template v-slot="{td}">
<template v-for="(col) in td.columns">
<preview-item
:model="col"
v-model="form[col.id]"
@valChange="handlerValChange"
/>
</template>
</template>
</fancy-edit-table>
<!--item-->
<el-col class="drag-col-wrapper" :key="index" :span="element.span" v-else>
<preview-item
:model="element"
v-model="form[element.id]"
@valChange="handlerValChange"
/>
</el-col>
</template>
</el-form>
</el-row>
<el-divider></el-divider>
<div style="text-align: center;">
<span slot="footer" class="dialog-footer">
<el-button type="primary" @click="handlerSubForm">提交</el-button>
</span>
</div>
</div>
</template>
<script>
import previewItem from "./previewItem";
import previewRowItem from "./previewRowItem";
import fancyDynamicTable from "./dynamic/fancyDynamicTable";
import fancyDynamicTableItem from "./dynamic/fancyDynamicTableItem";
import fancyEditTable from "./table/fancyEditTable";
import {datas,addRow,batchDeleteRow,deleteRow} from "./custom/formDraw";
export default {
name:'preview',
props:['itemList','formConf'],
components:{
previewItem,
previewRowItem,
fancyDynamicTable,
fancyDynamicTableItem,
fancyEditTable
},
data(){
return{
list: this.itemList,
form:{},
rules:{},
currentIndex:-1
}
},
methods:{
handlerValChange(key,origin){
console.log(key);
this.$set(this.form,key,origin);
},
handlerDynamicValChange(parentId,index,key,origin){
this.$set(this.form[parentId][index],key,origin);
this.currentIndex = index;
},
handlerSubForm(){
this.$refs[this.formConf.formModel].validate((valid) => {
if (valid) {
this.$message.success('success');
}
});
},
handlerAddRow:addRow,
handlerDeleteRow:deleteRow,
handlerBatchDeleteRow:batchDeleteRow,
handlerInitDatas:datas,
},
created(){
this.handlerInitDatas();//初始化表单
},
mounted() {
this.$nextTick(()=> {
})
},
beforeCreate(){
},
computed:{
}
}
</script>
<style scoped>
.preview-board{
border: 1px dashed #ccc
}
.preview >>> .el-radio.is-bordered+.el-radio.is-bordered{
margin-left:0px;
}
.preview >>> .el-checkbox.is-bordered+.el-checkbox.is-bordered{
margin-left:0px;
}
</style>
\ No newline at end of file
<script>
import render from './custom/previewRender'
import checkRules from './custom/rule';
const layouts = {
colItem(h, element,value) {
let labelWidth = element.labelWidth ? `${element.labelWidth}px` : null
const {valChange} = this.$listeners;
const rules = checkRules(element);
return (
<el-col style="padding-left: 7.5px; padding-right: 7.5px;">
<el-form-item label={element.showLabel ? element.label : ''}
label-width={labelWidth}
prop={element.id}
rules={rules}
>
<render key={element.id} conf={element} value={value} onInput={ event => {
this.$set(element,'value',event);
valChange(element.id,event);
}}/>
</el-form-item>
</el-col>
)
}
}
export default {
name:"previewItem",
components: {
render
},
props: ['model','value'],
data(){
return {
eleConfig:this.model
}
},
render(h) {
return layouts.colItem.call(this, h, this.eleConfig,this.value)
}
}
</script>
<style scoped>
.el-form-item{
margin-left:10px;
margin-right:10px;
margin-bottom: 5px;
}
</style>
\ No newline at end of file
<template>
<el-col>
<el-row :gutter="model.gutter">
<div class="drag-wrapper">
<slot></slot>
</div>
</el-row>
</el-col>
</template>
<script>
export default {
name:"previewRowItem",
components: {
},
props: ['model','value'],
data(){
return {
}
},
computed:{
}
}
</script>
\ No newline at end of file
body{
margin:0px;
}
.container {
position: relative;
width: 100%;
height: 100%;
}
.left-board {
width: 260px;
position: absolute;
left: 0;
top: 0;
height: 100vh;
}
.d-logo-wrapper{
position: relative;
height: 42px;
background: #ffffff;
border-bottom: 1px solid #f1e8e8;
box-sizing: border-box;
}
.d-logo{
position: absolute;
left: 12px;
top: 6px;
line-height: 30px;
color: #409eff;
font-weight: 600;
font-size: 17px;
white-space: nowrap;
}
.d-logo img{
width: 30px;
height: 30px;
vertical-align: top;
}
.components-title{
font-size: 14px;
color: #222;
margin: 6px 6px;
font-weight:700
}
.components-draggable{
padding-bottom: 20px;
}
.components-list {
padding: 8px;
box-sizing: border-box;
height: 100%;
}
.components-list .components-item {
display: inline-block;
width: 48%;
margin: 1%;
transition: transform 0ms !important;
}
.components-body {
padding: 8px 10px;
background: #f4f6fc;
font-size: 12px;
margin-left: 5px;
padding-top: 5px;
cursor: move;
border: 1px solid #409eff;
border-radius: 3px;
}
.components-body:hover {
border: 1px dashed #f56c6c;
color: #f56c6c;
}
.center-board {
height: 100vh;
width: auto;
margin: 0 350px 0 260px;
box-sizing: border-box;
}
.empty-info{
position: absolute;
top: 30%;
left: 0;
right: 0;
text-align: center;
font-size: 18px;
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;
background: #ffffff;
}
.action-bar .el-button{
font-size: 18px;
vertical-align: middle;
position: relative;
top: -1px;
color:#409EFF
}
.action-bar .delete-btn{
color: #F56C6C;
}
.center-scrollbar {
height: calc(100vh - 42px);
overflow: hidden;
border-left: 1px solid #f1e8e8;
border-right: 1px solid #f1e8e8;
box-sizing: border-box;
}
.center-board-row {
padding: 10px 12px 100px 12px;
box-sizing: border-box;
}
.center-board-row .el-form {
height: calc(100vh - 69px);
}
.dynamic-table{
margin: 0px;
height: auto;
min-height: 120px;
padding: 10px 0px;
}
.dynamic-table__content{
width:100%;
height:100%;
display: flex;
overflow-y: hidden;
outline: 1px dashed #ccc;
outline-offset: -1px;
min-height: 100px;
float:left
}
.dynamic-table__item {
margin:1px;
padding-top:5px;
border: 1px solid #EBEEF5;
background:#f2f6fc;
border-radius: 2px;
}
.dynamic-table__item:hover {
border: 1px solid #409EFF;
}
.dynamic-table__item_title{
width:100%;
padding-top:8px;
line-height: 23px;
text-align: center;
border-bottom: 1px solid #EBEEF5;
font-size: 14px;
color:#606266;
height:30px;
}
.dynamic-table__item_body{
padding:10px;
text-align: center;
}
.table__content{
width:100%;
height:100%;
overflow-y: hidden;
outline: 1px dashed #ccc;
outline-offset: -1px;
min-height: 100px;
float:left
}
.el-radio:last-child {
margin-right:30px;
}
.el-checkbox:last-of-type{
margin-right:30px;
}
.el-rate{
margin-top:10px;
}
.component-id{
position: absolute;
top: 0;
left: 0;
font-size: 12px;
color: #bbb;
display: inline-block;
margin: 0 6px;
}
/* .dynamic-table.active{
border-left: 3px solid #409eff;
background:#ecf5ff
} */
\ No newline at end of file
$selectedColor: #e6f2ff;
$lighterBlue: #409EFF;
.drawing-board {
height: 100%;
position: relative;
border:1px dashed #ccc;
.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: #409EFF;
z-index: 2;
}
}
.components-item.sortable-ghost {
width: 100%;
height: 5px;
background-color: $selectedColor;
}
.drawing-item.sortable-ghost {
width: 100%;
height: 5px;
background-color: $selectedColor;
}
.active-from-item {
& > .el-form-item{
background: $selectedColor;
border-radius:6px;
margin-top:15px;
}
& > .dynamic-table{
background: $selectedColor;
border-radius:6px;
}
& > .drawing-item-copy, & > .drawing-item-delete{
display: initial;
}
& > .component-name{
color: $lighterBlue;
}
}
.el-form-item{
margin-bottom: 5px;
}
}
.drawing-item{
position: relative;
cursor: move;
&.unfocus-bordered:not(.active-from-item) > div:first-child {
border: 1px dashed #ccc;
}
.el-form-item{
padding: 12px 10px;
margin-top:15px;
}
}
.drawing-item{
position: relative;
border: 1px dashed #ccc;
cursor: move;
.dynamic-table{
padding: 12px 5px;
}
}
.drawing-row-item{
position: relative;
cursor: move;
box-sizing: border-box;
border: 1px dashed #ccc;
border-radius: 3px;
padding: 0 2px;
margin-bottom: 15px;
.el-col{
margin-top: 15px;
}
.el-form-item{
margin-bottom: 15px;
}
.drag-wrapper{
min-height: 80px;
}
.drag-col-wrapper{
height: auto;
border: 1px dashed #ccc;
}
&.active-from-item{
border: 2px solid #e6a23c;
}
.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: #ebeef5;
}
& > .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;
}
}
}
.drawing-item, .drawing-form-item{
&:hover {
& > .el-form-item{
background: #ebeef5;
}
& > .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;
}
}
}
.right-board {
width: 350px;
position: absolute;
right: 0;
top: 0;
padding-top: 3px;
.field-box {
position: relative;
height: calc(100vh - 42px);
box-sizing: border-box;
overflow: hidden;
}
.el-scrollbar {
height: 100%;
}
}
.select-item {
display: flex;
border: 1px dashed #fff;
box-sizing: border-box;
& .close-btn {
cursor: pointer;
color: #f56c6c;
}
& .el-input + .el-input {
margin-left: 4px;
}
}
.select-item + .select-item {
margin-top: 4px;
}
.select-item.sortable-chosen {
border: 1px dashed #409eff;
}
.select-line-icon {
line-height: 32px;
font-size: 22px;
padding: 0 4px;
color: #777;
}
.option-drag {
cursor: move;
}
.time-range {
.el-date-editor {
width: 227px;
}
::v-deep .el-icon-time {
display: none;
}
}
.document-link {
position: absolute;
display: block;
width: 26px;
height: 26px;
top: 0;
left: 0;
cursor: pointer;
background: #409eff;
z-index: 1;
border-radius: 0 0 6px 0;
text-align: center;
line-height: 26px;
color: #fff;
font-size: 18px;
}
.node-label{
font-size: 14px;
}
.node-icon{
color: #bebfc3;
}
.center-tabs{
.el-tabs__header{
margin-bottom: 0!important;
}
.el-tabs__item{
width: 100%;
text-align: center;
}
.el-tabs__nav{
width: 100%;
}
}
.right-scrollbar {
.el-scrollbar__view {
padding: 12px 18px 15px 15px;
}
}
.drawing-row-item .el-col{
margin-bottom:5px;
}
.components-item.dynamicGhost {
width: 5px;
height: 120px;
background-color: #409EFF;
}
.dynamic-table_item.dynamicGhost {
width: 5px;
height: 120px;
background-color: #409EFF;
}
<template>
<div>
<div style="padding:5px;margin-top:10px">
<table class="table-layout" :style="tableWidth">
<tbody>
<tr v-for="(tr, trIndex) in layoutArray" :key="trIndex" :style="trHeight">
<fancy-edit-table-item v-for="(td,tdIndex) in tr" :key="tdIndex"
:item="td"
:tdIndex="tdIndex"
:trIndex="trIndex"
:tdStyle="tdStyle"
>
<slot :td="td" />
</fancy-edit-table-item>
</tr>
</tbody>
</table>
</div>
</div>
</template>
<script>
import fancyEditTableItem from './fancyEditTableItem';
export default {
name: 'fancyEditTable',
components: {
fancyEditTableItem
},
props: {
layoutArray: {
type: Array,
default: () => []
},
tdStyle:{
type:String,
default:''
},
width:{
type:Number,
default:100
},
height:{
type:Number,
default:100
}
},
data() {
return {
}
},
mounted() {
},
destroyed() {
},
methods: {
},
computed: {
tableWidth(){
return 'width:'+this.width+'%';
},
trHeight(){
return 'height:'+this.height+'px';
}
}
}
</script>
<style scoped>
table {
border-spacing: 0;
width: 100%
}
tbody {
display: table-row-group;
vertical-align: middle;
border-color: inherit;
}
td {
border: 1px #d2d2d2 solid;
}
.table-layout {
background-color: #ffffff;
border-collapse: collapse;
padding: 8px !important;
text-align: left;
margin: 0 auto;
width: 100%;
table-layout: fixed;
}
.table-layout>tbody>tr>td {
padding: 6px;
word-break: break-word;
border: 1px solid #d2d2d2;
height: 20px;
}
.table-layout>tbody>tr {
border-bottom: 1px solid #d2d2d2;
border-top: 1px solid #d2d2d2;
}
.right-menu {
background-color: #ffffff;
z-index: 100;
width: 200px;
position: fixed;
border: 1px solid #ccc;
box-shadow: 3px 3px 8px #999;
border-radius: 3px;
padding: 8px 0;
}
.right-menu ul {
margin: 0px;
padding: 0px;
}
.right-menu ul li {
padding: 0 15px;
height: 30px;
line-height: 30px;
}
.right-menu ul li:hover {
cursor: pointer;
background-color: #ccc;
}
.CellHide {
display: none;
}
</style>
\ No newline at end of file
<template>
<td
:colspan="item.col"
:rowspan="item.row"
:class="{cellHide:item.hide} "
:style="{tdStyle,'background-color':item.style.background,'width':item.style.width+'%'}"
style=""
@contextmenu.prevent="rightClick($event,trIndex,tdIndex)"
>
<slot :td="item" />
</td>
</template>
<script>
export default {
name:'fancyEditTableItem',
components:{
},
props:{
item: {
type: Object,
default:{}
},
tdIndex: {
type: Number,
default:0
},
trIndex: {
type: Number,
default:0
},
tdStyle: {
type: String,
default:''
}
}
}
</script>
<style scoped>
td{
border:1px #d2d2d2 solid;
padding: 6px;
padding-top:0px;
word-break: break-word;
border: 1px solid #d2d2d2;
height: 20px;
height:20px;
}
.cellHide{
display: none;
}
.activeItem{
border:2px solid #e6a23c
}
.component-td{
font-size:12px;
color:#bbb;
}
.activeItem div span{
color:#409EFF
}
</style>
\ No newline at end of file
<template>
<div>
<div style="padding:5px;margin-top:10px">
<table class="table-layout" :style="tableStyle">
<tbody>
<tr v-for="(tr,trIndex) in layoutArray" :key="trIndex" :style="trHeight">
<fancy-table-item v-for="(td,tdIndex) in tr" :key="tdIndex"
:item="td"
:tdIndex="tdIndex"
:trIndex="trIndex"
:tdStyle="tdStyle"
@rightClick="rightClick"
@click.native="handlerSelectedTd($event,td)"
>
<slot :td="td" />
</fancy-table-item>
</tr>
</tbody>
</table>
</div>
<div v-show="showContextMunu" class="right-menu" :style="{ top: + positionY+'px',left: + positionX+'px', }">
<ul style="list-style-type: none">
<li @click="handlerRightCol" v-if="showRightColMenu">
<icon code="zuoyouhebing" text="向右合并单元格" />
</li>
<li @click="handlerDownRow" v-if="showDownRowMenu">
<icon code="shangxiahebing" text="向下合并单元格" />
</li>
<li @click="handlerResetTable" v-if="showResetTableMenu">
<icon code="chaifen" text="拆分单元格" />
</li>
<li @click="handlerAppendCol">
<icon code="zhuijiahang" text="追加行" />
</li>
<li @click="handlerAppendRow">
<icon code="zhuijialie" text="追加列" />
</li>
</ul>
</div>
</div>
</template>
<script>
import icon from '../icon';
import fancyTableItem from './fancyTableItem';
import {jsonClone} from "../utils";
import {getTrItem,getTdItem} from "./table";
import { getSimpleId } from '../utils/IdGenerate';
let tr = getTrItem();
export default {
name:'fancyTable',
components:{
icon,
fancyTableItem
},
props:{
layoutArray:{
type:Array,
default:()=>[]
},
tdStyle:{
type:String,
default:''
},
width:{
type:Number,
default:100
},
height:{
type:Number,
default:100
}
},
data(){
return{
positionX:0,
positionY:0,
showContextMunu:false,
currentRowIndex:0,
currentColIndex:0,
//columns: this.trs
}
},
mounted() {
// 添加监听取消右键菜单
document.addEventListener("click", this.hideRightContextMenu, true);
document.addEventListener("contextmenu", this.hideRightContextMenu, true);
// this.handlerAppendCol();
// this.handlerAppendCol();
},
destroyed() {
// 移除监听
document.removeEventListener("click", this.hideRightContextMenu, true);
document.removeEventListener("contextmenu",this.hideRightContextMenu,true);
},
methods:{
rightClick(e,rowIndex,colIndex){
this.positionX = e.clientX;
this.positionY = e.clientY;
this.showContextMunu = true;
this.currentRowIndex = rowIndex;
this.currentColIndex = colIndex;
},
hideRightContextMenu(){
this.showContextMunu = false;
},
//向右合并单元格
handlerRightCol(){
let col = this.layoutArray[this.currentRowIndex][this.currentColIndex].col;
let row = this.layoutArray[this.currentRowIndex][this.currentColIndex].row;
if(row>1){
for(let i =0;i<row;i++){
this.layoutArray[this.currentRowIndex+i][this.currentColIndex+col].hide=true;
this.layoutArray[this.currentRowIndex][this.currentColIndex].col=col+1;
}
}else{
this.layoutArray[this.currentRowIndex][this.currentColIndex+col].hide=true;
this.layoutArray[this.currentRowIndex][this.currentColIndex].col=col+1;
}
},
//向下合并单元格
handlerDownRow(){
let col = this.layoutArray[this.currentRowIndex][this.currentColIndex].col;
let row = this.layoutArray[this.currentRowIndex][this.currentColIndex].row;
if(col>1){
for(let i =0;i<col;i++){
this.layoutArray[this.currentRowIndex+row][this.currentColIndex+i].hide=true;
this.layoutArray[this.currentRowIndex][this.currentColIndex].row=row+1;
}
}else{
this.layoutArray[this.currentRowIndex+row][this.currentColIndex].hide=true;
this.layoutArray[this.currentRowIndex][this.currentColIndex].row=row+1;
}
// let nextCol = this.columns[this.currentRowIndex+1][this.currentColIndex].col;
// let nextRow = this.columns[this.currentRowIndex+1][this.currentColIndex].row;
// if(nextCol<2&nextRow<2){
// }else{
// alert('请先拆分下方单元格!');
// }
},
handlerResetTable(){
//debugger;
let col = this.layoutArray[this.currentRowIndex][this.currentColIndex].col;
let row = this.layoutArray[this.currentRowIndex][this.currentColIndex].row;
if(col===1&&row===1)return;
for(let i = 0;i<row;i++){
for(let j = 0;j<col;j++){
this.layoutArray[this.currentRowIndex+i][this.currentColIndex+j].hide = false;
}
}
this.layoutArray[this.currentRowIndex][this.currentColIndex].row=1;
this.layoutArray[this.currentRowIndex][this.currentColIndex].col=1;
},
handlerSelectedTd(e,td){
this.$emit('selectItem',td);
e.stopPropagation();
},
//追加行
handlerAppendCol(){
let _trItem = jsonClone(tr);
_trItem.map(item=>item.id=getSimpleId());
this.layoutArray.push(_trItem);
},
handlerAppendRow(){
tr.push(getTdItem());
this.layoutArray.forEach(item=>{
const _td = jsonClone(getTdItem());
item.push(_td);
})
}
},
computed:{
showRightColMenu(){
if(this.showContextMunu){
const col = this.layoutArray[this.currentRowIndex][this.currentColIndex].col;
const td = this.layoutArray[this.currentRowIndex][this.currentColIndex+col];
return (td&&td.row<2&&td.col<2&&!td.hide);
}else{
return false;
}
},
showDownRowMenu(){
if(this.showContextMunu){
const row = this.layoutArray[this.currentRowIndex][this.currentColIndex].row;
let td = undefined;
if(typeof this.layoutArray[this.currentRowIndex+row] !== 'undefined'){
td = this.layoutArray[this.currentRowIndex+row][this.currentColIndex];
}
return (td&&td.row<2&&td.col<2&&!td.hide);
}else{
return false;
}
},
showResetTableMenu(){
if(this.showContextMunu){
const td = this.layoutArray[this.currentRowIndex][this.currentColIndex];
return !(td.row<2&&td.col<2&&!td.hide);
}else{
return false;
}
},
tableStyle(){
return 'width:'+this.width+'%;';
},
trHeight(){
return 'height:'+this.height+'px';
}
}
}
</script>
<style scoped>
table{
border-spacing:0;
width:100%
}
tbody{
display: table-row-group;
vertical-align: middle;
border-color: inherit;
}
.table-layout{
background-color: #ffffff;
border-collapse: collapse;
padding: 8px !important;
text-align: left;
margin: 0 auto;
width: 100%;
table-layout: fixed;
}
.table-layout > tbody > tr{
border-bottom: 1px solid #d2d2d2;
border-top: 1px solid #d2d2d2;
}
.right-menu{
background-color:#ffffff;
z-index:100;
width:200px;
position: fixed;
border: 1px solid #ccc;
box-shadow: 3px 3px 8px #999;
border-radius: 3px;
padding: 8px 0;
}
.right-menu ul{
margin:0px;
padding:0px;
}
.right-menu ul li{
padding:0 15px;
height:30px;
line-height: 30px;
}
.right-menu ul li:hover{
cursor: pointer;
background-color: #ccc;
}
</style>
\ No newline at end of file
<template>
<td
:colspan="item.col"
:rowspan="item.row"
:class="{cellHide:item.hide,activeItem:isActiveItem} "
:style="{tdStyle,'background-color':item.style.background,'width':item.style.width+'%'}"
style=""
@contextmenu.prevent="rightClick($event,trIndex,tdIndex)"
>
<div class="component-td">
<span >{{item.id}}</span>
<slot :td="item" />
</div>
</td>
</template>
<script>
export default {
name:'fancyTableItem',
components:{
},
props:{
item: {
type: Object,
default:{}
},
tdIndex: {
type: Number,
default:0
},
trIndex: {
type: Number,
default:0
},
tdStyle: {
type: String,
default:''
}
},
data(){
return{
}
},
inject:['getContext'],
methods:{
rightClick(e,rowIndex,colIndex){
this.$emit('rightClick',e,rowIndex,colIndex);
}
},
computed:{
isActiveItem() {
return this.getContext.activeItem.id===this.item.id?true:false;
//this.designerActiveItem
}
}
}
</script>
<style scoped>
td{
border:1px #d2d2d2 solid;
padding: 6px;
padding-top:0px;
word-break: break-word;
border: 1px solid #d2d2d2;
height: 20px;
height:20px;
}
.cellHide{
display: none;
}
.activeItem{
border:2px solid #e6a23c
}
.component-td{
font-size:12px;
color:#bbb;
}
.activeItem div span{
color:#409EFF
}
</style>
\ No newline at end of file
import {getSimpleId} from "../utils/IdGenerate";
import constant from '../utils/constants'
import {jsonClone} from "../utils";
let tdItemObj = {
id:'',
col:1,
row:1,
hide:false,
compType:'tdItem',
style:{
background:constant.defaultTdBackgroundColor,
width:35
},
columns:[]
}
export function getTdItem(){
let tdItem = cloneObj(tdItemObj);
tdItem.id = getSimpleId();
return tdItem;
}
export function getTitleTdItem(){
let tdItem = cloneObj(tdItemObj);
tdItem.style.background = constant.defaultTitleTdBackgroundColor;
tdItem.style.width = 15;
tdItem.id = getSimpleId();
return tdItem;
}
function cloneObj(source){
let target = jsonClone(source);
target.id = getSimpleId();
return target;
}
export function getTrItem(){
let trItem= [getTitleTdItem(),getTdItem(),getTitleTdItem(),getTdItem()];
return trItem;
}
export function getDefaultTrs(){
let trs = [getTrItem(),getTrItem()];
return trs;
}
\ No newline at end of file
export function getSimpleId(){
sleep(10); //主要为了延时工作
return new Date().getTime();
}
const sleep = function(time) {
const startTime = new Date().getTime() + parseInt(time, 10);
while(new Date().getTime() < startTime) {}
};
export function setTableId(table){
table.layoutArray.map((tr,trIndex)=>{
tr[0].id=getSimpleId();
tr[1].id=getSimpleId();
})
return table;
}
\ No newline at end of file
import allData from 'china-area-data/v5/data';
export function areaData(){
let options = [];
const allProvinceData = allData['86']; //得到全中国的省
Object.keys(allProvinceData).forEach(key=>{
let provinceObj={};
provinceObj.label= allProvinceData[key];
provinceObj.value= key;
const cityData = allData[key]; //市
provinceObj.children = [];
Object.keys(cityData).forEach(ckey=>{
let cityObj = {};
cityObj.label = cityData[ckey];
cityObj.value = ckey;
const areaData = allData[ckey]; //区
if(typeof areaData !== 'undefined'){
cityObj.children = [];
Object.keys(areaData).forEach(akey=>{
let areaObj = {};
areaObj.label = areaData[akey];
areaObj.value = akey;
cityObj.children.push(areaObj);
});
}
provinceObj.children.push(cityObj);
})
options.push(provinceObj);
});
return options;
}
/**
* js的常量就在这里
*/
export default {
defaultTdBackgroundColor:'#FFFFFF',
defaultTitleTdBackgroundColor:'#F6F6F6'
}
\ No newline at end of file
[
"el-icon-platform-eleme",
"el-icon-eleme",
"el-icon-delete-solid",
"el-icon-delete",
"el-icon-s-tools",
"el-icon-setting",
"el-icon-user-solid",
"el-icon-user",
"el-icon-phone",
"el-icon-phone-outline",
"el-icon-more",
"el-icon-more-outline",
"el-icon-star-on",
"el-icon-star-off",
"el-icon-s-goods",
"el-icon-goods",
"el-icon-warning",
"el-icon-warning-outline",
"el-icon-question",
"el-icon-info",
"el-icon-remove",
"el-icon-circle-plus",
"el-icon-success",
"el-icon-error",
"el-icon-zoom-in",
"el-icon-zoom-out",
"el-icon-remove-outline",
"el-icon-circle-plus-outline",
"el-icon-circle-check",
"el-icon-circle-close",
"el-icon-s-help",
"el-icon-help",
"el-icon-minus",
"el-icon-plus",
"el-icon-check",
"el-icon-close",
"el-icon-picture",
"el-icon-picture-outline",
"el-icon-picture-outline-round",
"el-icon-upload",
"el-icon-upload2",
"el-icon-download",
"el-icon-camera-solid",
"el-icon-camera",
"el-icon-video-camera-solid",
"el-icon-video-camera",
"el-icon-message-solid",
"el-icon-bell",
"el-icon-s-cooperation",
"el-icon-s-order",
"el-icon-s-platform",
"el-icon-s-fold",
"el-icon-s-unfold",
"el-icon-s-operation",
"el-icon-s-promotion",
"el-icon-s-home",
"el-icon-s-release",
"el-icon-s-ticket",
"el-icon-s-management",
"el-icon-s-open",
"el-icon-s-shop",
"el-icon-s-marketing",
"el-icon-s-flag",
"el-icon-s-comment",
"el-icon-s-finance",
"el-icon-s-claim",
"el-icon-s-custom",
"el-icon-s-opportunity",
"el-icon-s-data",
"el-icon-s-check",
"el-icon-s-grid",
"el-icon-menu",
"el-icon-share",
"el-icon-d-caret",
"el-icon-caret-left",
"el-icon-caret-right",
"el-icon-caret-bottom",
"el-icon-caret-top",
"el-icon-bottom-left",
"el-icon-bottom-right",
"el-icon-back",
"el-icon-right",
"el-icon-bottom",
"el-icon-top",
"el-icon-top-left",
"el-icon-top-right",
"el-icon-arrow-left",
"el-icon-arrow-right",
"el-icon-arrow-down",
"el-icon-arrow-up",
"el-icon-d-arrow-left",
"el-icon-d-arrow-right",
"el-icon-video-pause",
"el-icon-video-play",
"el-icon-refresh",
"el-icon-refresh-right",
"el-icon-refresh-left",
"el-icon-finished",
"el-icon-sort",
"el-icon-sort-up",
"el-icon-sort-down",
"el-icon-rank",
"el-icon-loading",
"el-icon-view",
"el-icon-c-scale-to-original",
"el-icon-date",
"el-icon-edit",
"el-icon-edit-outline",
"el-icon-folder",
"el-icon-folder-opened",
"el-icon-folder-add",
"el-icon-folder-remove",
"el-icon-folder-delete",
"el-icon-folder-checked",
"el-icon-tickets",
"el-icon-document-remove",
"el-icon-document-delete",
"el-icon-document-copy",
"el-icon-document-checked",
"el-icon-document",
"el-icon-document-add",
"el-icon-printer",
"el-icon-paperclip",
"el-icon-takeaway-box",
"el-icon-search",
"el-icon-monitor",
"el-icon-attract",
"el-icon-mobile",
"el-icon-scissors",
"el-icon-umbrella",
"el-icon-headset",
"el-icon-brush",
"el-icon-mouse",
"el-icon-coordinate",
"el-icon-magic-stick",
"el-icon-reading",
"el-icon-data-line",
"el-icon-data-board",
"el-icon-pie-chart",
"el-icon-data-analysis",
"el-icon-collection-tag",
"el-icon-film",
"el-icon-suitcase",
"el-icon-suitcase-1",
"el-icon-receiving",
"el-icon-collection",
"el-icon-files",
"el-icon-notebook-1",
"el-icon-notebook-2",
"el-icon-toilet-paper",
"el-icon-office-building",
"el-icon-school",
"el-icon-table-lamp",
"el-icon-house",
"el-icon-no-smoking",
"el-icon-smoking",
"el-icon-shopping-cart-full",
"el-icon-shopping-cart-1",
"el-icon-shopping-cart-2",
"el-icon-shopping-bag-1",
"el-icon-shopping-bag-2",
"el-icon-sold-out",
"el-icon-sell",
"el-icon-present",
"el-icon-box",
"el-icon-bank-card",
"el-icon-money",
"el-icon-coin",
"el-icon-wallet",
"el-icon-discount",
"el-icon-price-tag",
"el-icon-news",
"el-icon-guide",
"el-icon-male",
"el-icon-female",
"el-icon-thumb",
"el-icon-cpu",
"el-icon-link",
"el-icon-connection",
"el-icon-open",
"el-icon-turn-off",
"el-icon-set-up",
"el-icon-chat-round",
"el-icon-chat-line-round",
"el-icon-chat-square",
"el-icon-chat-dot-round",
"el-icon-chat-dot-square",
"el-icon-chat-line-square",
"el-icon-message",
"el-icon-postcard",
"el-icon-position",
"el-icon-turn-off-microphone",
"el-icon-microphone",
"el-icon-close-notification",
"el-icon-bangzhu",
"el-icon-time",
"el-icon-odometer",
"el-icon-crop",
"el-icon-aim",
"el-icon-switch-button",
"el-icon-full-screen",
"el-icon-copy-document",
"el-icon-mic",
"el-icon-stopwatch",
"el-icon-medal-1",
"el-icon-medal",
"el-icon-trophy",
"el-icon-trophy-1",
"el-icon-first-aid-kit",
"el-icon-discover",
"el-icon-place",
"el-icon-location",
"el-icon-location-outline",
"el-icon-location-information",
"el-icon-add-location",
"el-icon-delete-location",
"el-icon-map-location",
"el-icon-alarm-clock",
"el-icon-timer",
"el-icon-watch-1",
"el-icon-watch",
"el-icon-lock",
"el-icon-unlock",
"el-icon-key",
"el-icon-service",
"el-icon-mobile-phone",
"el-icon-bicycle",
"el-icon-truck",
"el-icon-ship",
"el-icon-basketball",
"el-icon-football",
"el-icon-soccer",
"el-icon-baseball",
"el-icon-wind-power",
"el-icon-light-rain",
"el-icon-lightning",
"el-icon-heavy-rain",
"el-icon-sunrise",
"el-icon-sunrise-1",
"el-icon-sunset",
"el-icon-sunny",
"el-icon-cloudy",
"el-icon-partly-cloudy",
"el-icon-cloudy-and-sunny",
"el-icon-moon",
"el-icon-moon-night",
"el-icon-dish",
"el-icon-dish-1",
"el-icon-food",
"el-icon-chicken",
"el-icon-fork-spoon",
"el-icon-knife-fork",
"el-icon-burger",
"el-icon-tableware",
"el-icon-sugar",
"el-icon-dessert",
"el-icon-ice-cream",
"el-icon-hot-water",
"el-icon-water-cup",
"el-icon-coffee-cup",
"el-icon-cold-drink",
"el-icon-goblet",
"el-icon-goblet-full",
"el-icon-goblet-square",
"el-icon-goblet-square-full",
"el-icon-refrigerator",
"el-icon-grape",
"el-icon-watermelon",
"el-icon-cherry",
"el-icon-apple",
"el-icon-pear",
"el-icon-orange",
"el-icon-coffee",
"el-icon-ice-tea",
"el-icon-ice-drink",
"el-icon-milk-tea",
"el-icon-potato-strips",
"el-icon-lollipop",
"el-icon-ice-cream-square",
"el-icon-ice-cream-round"
]
\ No newline at end of file
export function makeMap(str, expectsLowerCase) {
const map = Object.create(null)
const list = str.split(',')
for (let i = 0; i < list.length; i++) {
map[list[i]] = true
}
return expectsLowerCase
? val => map[val.toLowerCase()]
: val => map[val]
}
/**
* num 小于0,左缩进num*2个空格; 大于0,右缩进num*2个空格。
* @param {string} str 代码
* @param {number} num 缩进次数
* @param {number} len 【可选】缩进单位,空格数
*/
export function indent(str, num, len = 2) {
if (num === 0) return str
const isLeft = num < 0; const result = []; let reg; let
spaces = ''
if (isLeft) {
num *= -1
reg = new RegExp(`(^\\s{0,${num * len}})`, 'g')
} else {
for (let i = 0; i < num * len; i++) spaces += ' '
}
str.split('\n').forEach(line => {
line = isLeft ? line.replace(reg, '') : spaces + line
result.push(line)
})
return result.join('\n')
}
// 首字母大小
export function titleCase(str) {
return str.replace(/( |^)[a-z]/g, L => L.toUpperCase())
}
// 下划转驼峰
export function camelCase(str) {
return str.replace(/-[a-z]/g, str1 => str1.substr(-1).toUpperCase())
}
export function isNumberStr(str) {
return /^[+-]?(0|([1-9]\d*))(\.\d+)?$/g.test(str)
}
export const beautifierConf = {
html: {
indent_size: '2',
indent_char: ' ',
max_preserve_newlines: '-1',
preserve_newlines: false,
keep_array_indentation: false,
break_chained_methods: false,
indent_scripts: 'separate',
brace_style: 'end-expand',
space_before_conditional: true,
unescape_strings: false,
jslint_happy: false,
end_with_newline: true,
wrap_line_length: '110',
indent_inner_html: true,
comma_first: false,
e4x: true,
indent_empty_lines: true
},
js: {
indent_size: '2',
indent_char: ' ',
max_preserve_newlines: '-1',
preserve_newlines: false,
keep_array_indentation: false,
break_chained_methods: false,
indent_scripts: 'normal',
brace_style: 'end-expand',
space_before_conditional: true,
unescape_strings: false,
jslint_happy: true,
end_with_newline: true,
wrap_line_length: '110',
indent_inner_html: true,
comma_first: false,
e4x: true,
indent_empty_lines: true
}
}
function stringify(obj) {
return JSON.stringify(obj, (key, val) => {
if (typeof val === 'function') {
return `${val}`
}
return val
})
}
function parse(str) {
return JSON.parse(str, (k, v) => {
if (v!==null&&v.indexOf && v.indexOf('function') > -1) {
return eval(`(${v})`)
}
return v
})
}
export function jsonClone(obj) {
return parse(stringify(obj));
}
export function isLayout(obj) {
return obj.compType === 'row';
}
export function isTable(obj) {
return obj.compType === 'table';
}
export function inTable(obj) {
return obj.col&&obj.row;
}
export const isAttr = makeMap(
'accept,accept-charset,accesskey,action,align,alt,async,autocomplete,'
+ 'autofocus,autoplay,autosave,bgcolor,border,buffered,challenge,charset,'
+ 'checked,cite,class,code,codebase,color,cols,colspan,content,http-equiv,'
+ 'name,contenteditable,contextmenu,controls,coords,data,datetime,default,'
+ 'defer,dir,dirname,disabled,download,draggable,dropzone,enctype,method,for,'
+ 'form,formaction,headers,height,hidden,high,href,hreflang,http-equiv,'
+ 'icon,id,ismap,itemprop,keytype,kind,label,lang,language,list,loop,low,'
+ 'manifest,max,maxlength,media,method,GET,POST,min,multiple,email,file,'
+ 'muted,name,novalidate,open,optimum,pattern,ping,placeholder,poster,'
+ 'preload,radiogroup,readonly,rel,required,reversed,rows,rowspan,sandbox,'
+ 'scope,scoped,seamless,selected,shape,size,type,text,password,sizes,span,'
+ 'spellcheck,src,srcdoc,srclang,srcset,start,step,style,summary,tabindex,'
+ 'target,title,type,usemap,value,width,wrap'
)
\ No newline at end of file
<template>
<layout-form>
<el-form :model="form" :loading="loading" :rules="rules" size='small' style="width:100%" label-width='120px' ref="form">
<el-row>
<Field label="模板ID" prop="templateId" v-model="form.templateId" placeholder="请输入模板ID"/>
<Field label="表单名称" prop="formName" v-model="form.formName" placeholder="请输入表单名称"/>
<el-col span="12">
<el-form-item label="表单内容">
<editor v-model="form.formContent" :min-height="192"/>
</el-form-item>
</el-col>
<Field label="备注" prop="remark" v-model="form.remark" placeholder="请输入备注"/>
</el-row>
<form-buttons @submit='submitForm'/>
</el-form>
</layout-form>
</template>
<script>
import form from "@/assets/mixins/form";
import Editor from '@/components/Editor';
export default {
mixins: [form],
components: {
Editor,
},
toString:[
],
methods: {
},
data() {
return {
rules: {
formName: [
{ trigger: "blur" },
],
formContent: [
{ trigger: "blur" },
],
remark: [
{ trigger: "blur" },
],
}
};
}
};
</script>
\ No newline at end of file
<template>
<div class="page">
<form-designer ref="formDesigner" :value="tmp" v-model="form.fdForm"></form-designer>
</div>
</template>
<script>
// import table from "@/assets/mixins/table";
export default {
components: {
},
// mixins: [table],
created() {
},
methods: {
},
data() {
return {
form:{
fdForm:''
},
tmp:''
};
}
};
</script>
\ No newline at end of file
// 添加,编辑设备
<template>
<!-- 弹出框表单 -->
<el-dialog :title="title" :visible.sync="open" width="35%" append-to-body>
<el-form
ref="form"
:model="form"
:rules="rules"
label-width="110px"
label-position="right"
>
<el-row>
<Field
:span="22"
label="ID"
prop="id"
v-model="form.id"
v-if="pageInfo.type !== 'add'"
disabled
/>
<Field :span="22" label="名称" prop="name" v-model="form.name" />
<Field
:span="22"
label="权限类型"
prop="authType"
v-model="form.authType"
:enumData="dict.authType"
type="select"
/>
<Field
:span="22"
label="父级菜单"
prop="parentId"
v-model="form.parentId"
:enumData="menu"
type="select"
/>
<Field :span="22" label="访问地址" prop="url" v-model="form.url" />
<Field
:span="22"
label="状态"
prop="status"
v-model="form.status"
:enumData="dict.status"
type="radio"
/>
<Field
:span="22"
label="图标"
placeholder="请输入图标名称"
prop="imgPath"
v-model="form.imgPath"
/>
<!-- <Field v-else :span="22" label="图标" prop="imgPath">
<el-radio-group v-model="form.imgPath" class="form-el-radio-group">
<el-radio-button label="">不需要图标</el-radio-button>
<el-radio-button
v-for="(icon, index) in icons"
:key="index"
:label="icon"
>
<i :class="'el-icon-' + icon"></i>
{{ icon }}
</el-radio-button>
</el-radio-group>
</Field> -->
</el-row>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button
type="primary"
v-if="pageInfo.type !== 'view'"
@click="submitForm"
>确 定</el-button
>
<el-button @click="cancel">取 消</el-button>
</div>
</el-dialog>
</template>
<script>
import form from "@/assets/mixins/formdialog";
import dialogShow from "./dialogshow";
export default {
mixins: [form],
components: {
dialogShow,
},
computed: {
menu() {
let menu = { 0: "" };
this.$store.state.userData.barList.forEach((item) => {
menu[item.id + ""] = item.name;
});
return menu;
},
},
methods: {
afterSubmit() {
this.$store.dispatch("login");
this.$router.go(-1);
},
/** 编辑 */
edit(row) {
this.reset();
this.query = { id: row.id };
this.urls.currUrl = this.pageInfo.editUrl;
this.getData();
this.pageInfo.type = "edit";
this.title = "修改菜单";
},
/** 新增 */
add(row) {
this.reset();
this.query = { id: row.id };
this.urls.currUrl = this.pageInfo.addUrl;
this.getData();
this.pageInfo.type = "add";
this.open = true;
this.title = "新增菜单";
},
/** 查看*/
view(row) {
this.reset();
this.query = { id: row.id };
this.urls.currUrl = this.pageInfo.viewUrl;
this.getData();
this.pageInfo.type = "view";
this.open = true;
this.title = "菜单详细";
},
/**取消按钮 */
cancel() {
this.open = false;
},
/**获取数据后弹框 */
afterRender(data) {
this.open = true;
},
afterSubmit(data) {
this.open = false;
this.$emit("ok");
},
// 表单重置
reset() {
// this.form={}
this.resetForm("form");
},
resetForm(refName) {
if (this.$refs[refName]) {
this.$refs[refName].resetFields();
}
},
},
data() {
return {
// 遮罩层
loading: true,
// 弹出层标题
title: "菜单",
// 是否显示弹出层
open: false,
toString: ["parentId", "authType", "status"],
icons: [
"info",
"error",
"success",
"warning",
"question",
"tickets",
"document",
"goods",
"sold-out",
"news",
"message",
"date",
"printer",
"time",
"bell",
"mobile-phone",
"service",
"view",
"menu",
"star-on",
"location",
"phone",
"picture",
"delete",
"search",
"edit",
"rank",
"refresh",
"share",
"setting",
"upload",
"upload2",
"download",
"loading",
"reading",
],
rules: {
name: [{ required: true, message: "请输入名称", trigger: "blur" }],
},
};
},
};
</script>
<style lang="less">
.el-select {
width: 100%;
}
.el-date-editor.el-input {
width: 100%;
}
.form-el-radio-group.label {
width: 160px;
}
.el-radio-button__inner {
border: 0;
}
</style>
<template>
<!-- 弹出框表单 -->
<el-dialog :title="title" :visible.sync="open" width="70%" append-to-body>
<el-form
:model="form"
:rules="rules"
size="small"
label-width="100px"
ref="form"
>
<el-row>
<Field label="参数名称" prop="name" v-model="form.name" />
<Field
label="一级组织"
prop="firstOrganize"
v-model="form.firstOrganize"
/>
<Field
label="二级组织"
prop="secondOrganize"
v-model="form.secondOrganize"
/>
<Field
label="参数有效状态"
prop="validStatus"
v-model="form.validStatus"
:enumData="dict.validStatus"
type="select"
/>
<Field
label="参数修改状态"
prop="modStatus"
v-model="form.modStatus"
:enumData="dict.modStatus"
type="select"
/>
<Field
label="展现类型"
prop="displayType"
v-model="form.displayType"
:enumData="dict.displayType"
type="select"
/>
<Field
label="参数键"
prop="paramKey"
v-model="form.paramKey"
:span="24"
/>
<Field
label="参数值"
prop="paramValue"
v-model="form.paramValue"
:span="24"
type="textarea"
/>
<Field label="备注" prop="remark" v-model="form.remark" :span="24" />
</el-row>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitForm">确 定</el-button>
<el-button @click="cancel">取 消</el-button>
</div>
</el-dialog>
</template>
<script>
import form from "@/assets/mixins/formdialog";
export default {
mixins: [form],
data() {
return {
// 遮罩层
loading: true,
// 弹出层标题
title: "站点信息",
// 是否显示弹出层
open: false,
toString: ["validStatus", "modStatus", "displayType"],
rules: {
name: [{ required: true, message: "请输入参数名称", trigger: "blur" }],
paramKey: [{ required: true, message: "请输入参数键", trigger: "blur" }],
paramValue: [{ required: true, message: "请输入参数值", trigger: "blur" }],
},
// urls:{list: "/para/file/list"}
};
},
methods: {
/** 编辑 */
edit(row) {
this.reset();
this.query = { id: row.id };
this.urls.currUrl = this.pageInfo.editUrl;
this.getData();
this.open = true;
this.title = "修改站点信息";
},
/** 新增 */
add(row) {
this.reset();
this.query = { id: row.id };
this.urls.currUrl = this.pageInfo.addUrl;
this.getData();
this.open = true;
this.title = "新增站点信息";
},
/** 查看*/
view(row) {
this.reset();
this.query = { id: row.id };
this.urls.currUrl = this.pageInfo.viewUrl;
this.getData();
this.open = true;
this.title = "站点信息详细";
},
/**取消按钮 */
cancel() {
this.reset();
this.open = false;
},
afterSubmit(data) {
this.open = false;
this.$emit("ok");
},
// 表单重置
reset() {
this.form = {
};
this.resetForm("form");
},
resetForm(refName) {
if (this.$refs[refName]) {
this.$refs[refName].resetFields();
}
},
},
};
</script>
<template>
<!-- 弹出框表单 -->
<el-dialog :title="title" :visible.sync="open" width="40%" append-to-body>
<el-form
ref="form"
:model="form"
:rules="rules"
label-width="110px"
label-position="right"
>
<el-row>
<Field :span="20" label="名称" prop="name" v-model="form.name" />
<Field
:span="20"
label="权限类型"
prop="authType"
v-model="form.authType"
:enumData="dict.authType"
type="select"
/>
<!-- <Field label="用户类型" prop="userType" v-model="form.userType" :enumData='dict.userType' type='select' /> -->
<Field label="链接地址" prop="url" :span="20">
<el-button
icon="el-icon-plus"
circle
size="mini"
@click="addResource"
v-if="!form.urls.length"
></el-button>
<el-row
v-for="(url, index) in form.urls"
:key="index"
style="width: 400px"
>
<el-col :span="16">
<el-form-item
label-width="0"
:prop="'urls.' + index + '.value'"
:rules="[
{ required: true, message: '地址不能为空', trigger: 'blur' },
{ validator: validatorUrl, trigger: 'blur' },
]"
>
<el-input size="mini" v-model="url.value"></el-input>
</el-form-item>
</el-col>
<el-col :span="8">
&nbsp;
<el-button
icon="el-icon-minus"
circle
size="mini"
@click="del(index)"
></el-button>
<el-button
icon="el-icon-plus"
circle
size="mini"
@click="addResource"
v-if="index === form.urls.length - 1"
></el-button>
</el-col>
</el-row>
</Field>
</el-row>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button
type="primary"
v-if="pageInfo.type !== 'view'"
@click="submitForm"
>确 定</el-button
>
<el-button @click="cancel">取 消</el-button>
</div>
</el-dialog>
</template>
<script>
import form from "@/assets/mixins/formdialog";
import dialogShow from "./dialogshow";
import FormButtons from "@/components/tools/FormButtons";
export default {
mixins: [form],
components: {
dialogShow,
FormButtons,
},
methods: {
beforeRender(data) {
data.entity.urls = (data.entity.url || "").split(",").map((i) => {
return { value: i };
});
return data;
},
beforeSubmit(form) {
form.url = this.form.urls.map((item) => item.value).join(",");
return form;
},
del(index) {
this.form.urls.splice(index, 1);
},
addResource(index) {
const urls = this.form.urls;
const values = urls.map((i) => i.value);
// 新增前检查前方是否有空行
if (urls.some((i) => !i.value)) {
return this.$message.warning("请先完成上一个地址的填写");
}
urls.push({ value: "" });
console.log("urls", urls);
},
isRepeat(value) {
return this.form.urls.filter((i) => value == i.value).length > 1;
},
validatorUrl(rule, value, cb) {
if (this.isRepeat(value)) {
return cb(new Error(`重复的url地址`));
}
cb();
},
/** 编辑 */
edit(row) {
this.reset();
this.query = { id: row.id };
this.urls.currUrl = this.pageInfo.editUrl;
this.getData();
this.pageInfo.type = "edit";
this.title = "修改资源";
},
/** 新增 */
add(row) {
this.reset();
this.query = { id: row.id };
this.urls.currUrl = this.pageInfo.addUrl;
this.getData();
this.pageInfo.type = "add";
this.title = "新增资源";
},
/** 查看*/
view(row) {
this.reset();
this.query = { id: row.id };
this.urls.currUrl = this.pageInfo.viewUrl;
this.getData();
this.pageInfo.type = "view";
this.title = "资源详细";
},
/**取消按钮 */
cancel() {
this.open = false;
},
/**获取数据后弹框 */
afterRender(data) {
// this.form.urls = (data.entity.url || "").split(",").map((i) => {
// return { value: i };
// });
this.open = true;
},
afterSubmit(data) {
this.open = false;
this.$emit("ok");
},
// 表单重置
reset() {
this.form = {
urls: [],
};
//this.resetForm("form");
},
resetForm(refName) {
if (this.$refs[refName]) {
this.$refs[refName].resetFields();
}
},
},
data() {
return {
// 遮罩层
loading: true,
// 弹出层标题
title: "资源",
// 是否显示弹出层
open: false,
toString: ["userType", "authType"],
form: {
urls: [],
},
rules: {
name: [{ required: true, message: "请输入名称", trigger: "blur" }],
},
};
},
};
</script>
<template>
<!-- 弹出框表单 -->
<el-dialog :title="title" :visible.sync="open" width="40%" append-to-body>
<el-form
ref="form"
:model="form"
:rules="rules"
label-width="110px"
label-position="right"
>
<el-row>
<Field :span="20" label="角色名" prop="name" v-model="form.name" />
<!-- <Field
:span="20"
label="角色类型"
prop="roleType"
v-model="form.roleType"
:enumData="dict.roleType"
type="select"
/> -->
<Field
label="备注"
prop="remark"
v-model="form.remark"
type="textarea"
:span="20"
/>
</el-row>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button
type="primary"
v-if="pageInfo.type !== 'view'"
@click="submitForm"
>确 定</el-button
>
<el-button @click="cancel">取 消</el-button>
</div>
</el-dialog>
</template>
<script>
import form from "@/assets/mixins/formdialog";
import dialogShow from "./dialogshow";
export default {
mixins: [form],
components: {
dialogShow,
},
data() {
return {
// 遮罩层
loading: true,
// 弹出层标题
title: "用户",
// 是否显示弹出层
open: false,
toString: ["roleType"],
rules: {
name: [{ required: true, message: "请输入名称", trigger: "blur" }],
roleType: [
{ required: true, message: "请选择用户类型", trigger: "blur" },
],
},
};
},
methods: {
/** 编辑 */
edit(row) {
this.reset();
this.query = { id: row.id };
this.urls.currUrl = this.pageInfo.editUrl;
this.getData();
this.pageInfo.type = "edit";
this.open = true;
this.title = "修改角色";
},
/** 新增 */
add(row) {
this.reset();
this.query = { id: row.id };
this.urls.currUrl = this.pageInfo.addUrl;
this.getData();
this.pageInfo.type = "add";
this.open = true;
this.title = "新增角色";
},
/** 查看*/
view(row) {
this.reset();
this.query = { id: row.id };
this.urls.currUrl = this.pageInfo.viewUrl;
this.getData();
this.pageInfo.type = "view";
this.open = true;
this.title = "角色详细";
},
/**取消按钮 */
cancel() {
this.open = false;
},
/**获取数据后弹框 */
afterRender(data) {
this.open = true;
},
afterSubmit(data) {
this.open = false;
this.$emit("ok");
},
// 表单重置
reset() {
this.form = {};
this.resetForm("form");
},
resetForm(refName) {
if (this.$refs[refName]) {
this.$refs[refName].resetFields();
}
},
},
};
</script>
// 添加,编辑设备
<template>
<!-- 弹出框表单 -->
<el-dialog :title="title" :visible.sync="open" width="80%" append-to-body>
<el-form
ref="form"
:model="form"
:rules="rules"
label-width="110px"
label-position="right"
>
<el-row>
<Field label="任务名称" prop="name" v-model="form.name"/>
<Field label="关键字" prop="taskKey" v-model="form.taskKey"/>
<Field label="执行服务" prop="excuteService" v-model="form.excuteService" :enumData='dict.excuteService' type='select' />
<Field label="执行策略" prop="excuteStrategy" @change='excuteStrategyChange' v-model="form.excuteStrategy" :enumData='dict.excuteStrategy' type='select' />
<Field :label="form.excuteStrategy == 4 ? '执行间隔时间' : '执行日期'" prop="excuteDate">
<el-input disabled value='每天' v-if='form.excuteStrategy == 1'></el-input>
<el-select v-model="form.excuteDate" v-if='form.excuteStrategy == 2'>
<el-option
v-for='($label, $value) in dict.week'
:key='$value'
:label="$label"
:value="$value"
></el-option>
</el-select>
<el-select v-model="form.excuteDate" v-if='form.excuteStrategy == 3'>
<el-option
v-for='($label, $value) in dict.days'
:key='$value'
:label="$label"
:value="$value"
></el-option>
</el-select>
<el-input v-model="form.excuteDate" v-if='form.excuteStrategy == 4'>
<template slot="append"></template>
</el-input>
</Field>
<Field label="执行时间" prop="excuteTime" v-if='form.excuteStrategy != 4'>
<el-time-select
v-model="form.excuteTime"
:picker-options="{
start: '00:00',
step: '00:5',
end: '23:45'
}"
placeholder="选择时间">
</el-time-select>
</Field>
<Field :span="24" label="执行主机" prop="excuteHost" v-model="form.excuteHost"/>
<Field :span="24" label="执行参数" prop="excuteParam" v-model="form.excuteParam" type='textarea' textareaSize/>
<Field :span="24" label="备注" prop="remark" v-model="form.remark" type='textarea' textareaSize/>
</el-row>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button
type="primary"
v-if="pageInfo.type !== 'view'"
@click="submitForm"
>确 定</el-button
>
<el-button @click="cancel">取 消</el-button>
</div>
</el-dialog>
</template>
<script>
import form from "@/assets/mixins/formdialog";
import dialogShow from "./dialogshow";
export default {
mixins: [form],
components: {
dialogShow,
},
methods: {
beforeRender(data) {
data.dict = data.dict || {};
const days = {};
[...new Array(31)].forEach((i,index)=>{
let key = index+1;
days[key] = `${key}号`;
})
data.dict.days = days;
data.dict.week = {
1: '星期一',
2: '星期二',
3: '星期三',
4: '星期四',
5: '星期五',
6: '星期六',
7: '星期天',
};
data.dict.excuteService = data.excuteService;
return data;
},
excuteStrategyChange(val) {
this.form.excuteDate = val == 1 ? '0' : '1';
},
/** 编辑 */
edit(row) {
this.reset();
this.query = { id: row.id };
this.urls.currUrl = this.pageInfo.editUrl;
this.getData();
this.pageInfo.type = "edit";
this.title = "修改任务";
},
/** 新增 */
add(row) {
this.reset();
this.query = { id: row.id };
this.urls.currUrl = this.pageInfo.addUrl;
this.getData();
this.pageInfo.type = "add";
this.title = "新增任务";
},
/** 查看*/
view(row) {
this.reset();
this.query = { id: row.id };
this.urls.currUrl = this.pageInfo.viewUrl;
this.getData();
this.pageInfo.type = "view";
this.title = "任务详细";
},
/**取消按钮 */
cancel() {
this.open = false;
},
/**获取数据后弹框 */
afterRender(data) {
console.log(this.form)
this.open = true;
},
afterSubmit(data) {
this.open = false;
this.$emit("ok");
},
// 表单重置
reset() {
this.form = {};
this.resetForm("form");
},
resetForm(refName) {
if (this.$refs[refName]) {
this.$refs[refName].resetFields();
}
},
},
data() {
return {
// 遮罩层
loading: true,
// 弹出层标题
title: "用户",
// 是否显示弹出层
open: false,
toString: ['excuteService', 'excuteStrategy', 'excuteDate'],
rules: {
name: [{ required: true, message: '请输入任务名称', trigger: 'blur' },],
taskKey: [{ required: true, message: '请输入任务关键字', trigger: 'blur' },],
excuteService: [{ required: true, message: '请选择任务执行服务', trigger: 'blur' },],
},
};
},
};
</script>
// 添加,编辑设备
<template>
<!-- 弹出框表单 -->
<el-dialog :title="title" :visible.sync="open" width="40%" append-to-body>
<el-form
ref="form"
:model="form"
:rules="rules"
label-width="110px"
label-position="right"
>
<el-row>
<Field
:span="20"
label="登录名称"
prop="loginName"
v-model="form.loginName"
/>
<Field :span="20" label="密码" prop="loginPwd">
<el-input
v-model.trim="form.loginPwd"
placeholder="请输入密码"
:type="passw"
clearable
@blur="onBlur"
>
<!-- input中加图标必须要有slot="suffix"属性,不然无法显示图标 -->
<i slot="suffix" :class="icon" @click="showPass"></i>
</el-input>
</Field>
<!-- <Field :span="20" label="登录密码" prop="loginPwd" v-model="form.loginPwd" /> -->
<Field
:span="20"
label="用户名称"
prop="realName"
v-model="form.realName"
/>
<Field
:span="20"
label="手机号码"
prop="mobile"
v-model="form.mobile"
/>
<!-- <Field label="用户类型" prop="userType" v-model="form.userType" :enumData='dict.userType' type='select' />
<Field label="用户状态" prop="status" v-model="form.status" :enumData='dict.status' type='select' /> -->
<Field
label="角色分配"
:span="24"
v-model="form.roleIds"
type="checkbox"
:enumData="dict.roleIds"
/>
</el-row>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button
type="primary"
v-if="pageInfo.type !== 'view'"
@click="submitForm"
>确 定</el-button
>
<el-button @click="cancel">取 消</el-button>
</div>
</el-dialog>
</template>
<script>
import form from "@/assets/mixins/formdialog";
import dialogShow from "./dialogshow";
export default {
mixins: [form],
components: {
dialogShow,
},
data() {
return {
// 遮罩层
loading: true,
// 弹出层标题
title: "用户",
// 是否显示弹出层
open: false,
toString: ["status", "userType"],
toArrays: ["roleIds"],
// 表单校验
rules: {
loginName: [
{ required: true, message: "请输入英文的用户名", trigger: "blur" },
{
validator: function (rule, value, callback) {
// 校验英文的正则
if (/[A-Za-z0-9]$/.test(value) == false) {
callback(new Error("请输入英文"));
} else {
//校验通过
callback();
}
},
trigger: "blur",
},
],
},
icon: "el-input__icon el-icon-view",
passw: "password",
SPAN: "24",
};
},
methods: {
/** 编辑 */
edit(row) {
this.reset();
this.query = { id: row.id };
this.urls.currUrl = this.pageInfo.editUrl;
this.getData();
this.pageInfo.type = "edit";
this.title = "修改用户";
},
/** 新增 */
add(row) {
this.reset();
this.query = { id: row.id };
this.urls.currUrl = this.pageInfo.addUrl;
this.getData();
this.pageInfo.type = "add";
this.title = "新增用户";
},
/** 查看*/
view(row) {
this.reset();
this.query = { id: row.id };
this.urls.currUrl = this.pageInfo.viewUrl;
this.getData();
this.pageInfo.type = "view";
this.title = "用户详细";
},
/**取消按钮 */
cancel() {
this.open = false;
},
/**获取数据后弹框 */
afterRender(data) {
this.open = true;
},
beforeSubmit(data) {
data.roleIds = data.roleIds
.filter((item) => {
return item !== "";
})
.join(",");
return data;
},
afterSubmit(data) {
this.open = false;
this.$emit("ok");
},
// 表单重置
reset() {
this.form = {roleIds:""};
this.resetForm("form");
},
resetForm(refName) {
if (this.$refs[refName]) {
this.$refs[refName].resetFields();
}
},
showPass() {
//点击图标是密码隐藏或显示
if (this.passw == "text") {
this.passw = "password";
//更换图标
this.icon = "el-input__icon el-icon-view";
} else {
this.passw = "text";
this.icon = "el-input__icon el-icon-loading";
setTimeout(() => {
this.icon = "";
}, 100);
}
},
//密码失焦事件
onBlur() {
this.passw = "password";
this.icon = "el-input__icon el-icon-view";
},
},
};
</script>
let treeData = [];
// 查找该条数据所处的层级深度
function getDeep(list, parentId, deep) {
try {
let pid = list.filter(i=>i.id == parentId)[0].parentId;
deep++;
if(pid != 0) {
return getDeep(list, pid, deep);
}else{
return deep
}
} catch (error) {
return deep;
}
}
// 分组排序
function sort(list) {
let array = [];
list.filter(i=>!i.parentId).forEach(item=>{
array = array.concat(child(list, item, []))
})
return array
}
function child(list, data, arr) {
arr.push(data);
if(data.hasChild) {
list.filter(i=>i.parentId==data.id).forEach(item=>{
return child(list, item, arr)
})
}
return arr;
}
let render = function(result) {
return treeData = sort(result.map(i=>{
i.hasChild = result.filter(j=>j.parentId==i.id).length > 0; // 是否有下级
i.deep = getDeep(result, i.parentId, 0); // 缩进层级
i.open = false;
i.isShow = true;
return i;
}));
}
let toggle = function(row) {
// 关闭的时候,需要递归关闭下面全部子级
let childId = []
// 打开下级
if(row.open) {
childId = child(treeData, row, []).map(i=>i.id)
childId.shift();
}
return treeData.map(i=>{
if(i.id == row.id) {
i.open = !i.open;
}
if(i.parentId == row.id) {
i.isShow = !i.isShow;
}
if(childId.indexOf(i.id) > -1) {
i.open = false;
i.isShow = childId.indexOf(i.id) === -1
}
return i;
})
.filter(i=>i.isShow)
}
function getParentId(id, list, arr) {
arr.unshift(id);
const pid = list.filter(i=>id == i.id)[0].parentId;
if(pid) {
return getParentId(pid, list, arr)
}else{
return arr;
}
}
function buildTree(pid, list) {
const data = list.filter(i=>pid == i.parentId);
return data.length ? data.map(i=>{
return {
value: i.id,
label: i.name,
children: buildTree(i.id, list),
}
}) : undefined
}
export default {
render,
toggle,
getParentId,
buildTree,
}
\ No newline at end of file
<template>
<div class="page">
<LayoutTable :data='tableData' :config='tableConfig' notPagination notDel>
<div>
<el-tree
:data="tree"
:props="treeProps"
:load="loadNode"
lazy>
<span style="width:100%" slot-scope="{ node, data }">
<span >{{ node.label }}</span>
<span style="float:right;">
<el-button
icon="el-icon-plus"
style="padding:3px 10px"
round
@click="() => addChild(data)">新增
</el-button>
<el-button
icon="el-icon-edit"
type="primary"
style="padding:3px 10px"
round
@click="() => editChild(data)"> 编辑
</el-button>
</span>
</span>
</el-tree>
</div>
</LayoutTable>
</div>
</template>
<script>
import table from "@/assets/mixins/table";
export default {
mixins: [table],
methods: {
async loadNode(node, resolve) {
if(node.level === 0) return
let res = await this.$post('/area/getAreaByParentId', {
'query.parentId': node.data.id,
'pageInfo.prePageResult': -1
});
resolve(this.clean(res.data.result));
},
clean(data) {
return data.map(i=>{
return {
name: i.name,
children: [],
id: i.id,
isLeaf: i.level > 2
}
});
},
afterRender({result}) {
this.tree = result;
},
addChild(data) {
this.$router.push({
path: this.pageInfo.add,
query: { pid: data.id }
});
},
editChild(data) {
this.$router.push({
path: this.pageInfo.edit,
query: Object.assign({}, {id: data.id}, this.query)
})
}
},
data() {
return {
tree:[],
openIds: [],
treeProps: {
children: 'children',
label: 'name',
isLeaf: 'isLeaf',
},
urls: {
del: "/area/disable"
},
query: {
pageInfo: {
prePageResult: -1
}
},
config: {
search: [
{
name: "name",
type: "text",
label: "名称"
},
{
name: "status",
type: "select",
label: "是否启用"
}
],
columns: [
{
type: "selection",
width: 60
},
{
label: "区域名称",
width: 200,
formatter: (row, col, val, index) => {
const width = `width: ${row.deep *
18}px;height: 20px;display: inline-block;`;
return (
<div>
<span style={width} />
{row.hasChild ? (
<i
onClick={() =>
this.loadArea(row)
}
class={
row.open
? "el-icon-caret-bottom"
: "el-icon-caret-right"
}
>
{row.name}
</i>
) : (
<span>{row.name}</span>
)}
</div>
);
}
},
{
prop: "id",
label: "区域ID"
},
{
prop: "parentId",
label: "上级区域ID"
},
{
prop: "name",
label: "区域名称"
},
{
prop: "level",
label: "区域级别",
width: 70,
formatter: this.formatter
},
{
prop: "code",
label: "区域编码"
},
// {
// prop: "contactsPeople",
// label: "区域负责人"
// },
// {
// prop: "contactsMobile",
// label: "区域负责人电话"
// },
{
prop: "status",
label: "启用",
formatter: this.formatter
},
{
prop: "remark",
label: "描述"
},
{
label: "操作",
width: 180,
formatter: row => {
return (
<div>
<el-button
icon="el-icon-plus"
size="mini"
round
onClick={() => {
this.addChild(row);
}}
>
新增
</el-button>{" "}
<table-buttons
row={row}
onEdit={this.toEdit}
noDel
/>
</div>
);
}
}
]
}
};
}
};
</script>
<template>
<layout-form>
<el-form
:model="form"
:loading="loading"
:rules="rules"
size='small'
label-width='120px'
ref="form"
>
<el-row>
<el-col :span='12'>
<el-form-item
label="区域"
prop="parentId"
>
<el-cascader
@change='treeSelected'
:options="treeData"
change-on-select
v-model="selectedTreeID"
></el-cascader>
</el-form-item>
</el-col>
<Field
label="区域名称"
prop="name"
v-model="form.name"
/>
<Field
label="区域级别"
prop="level"
v-model="form.level"
:enumData='dict.level'
type='select'
/>
<Field
label="编码"
prop="code"
v-model="form.code"
/>
<!-- <Field label="负责人" prop="contactsPeople" v-model="form.contactsPeople"/>
<Field label="负责人电话" prop="contactsMobile" v-model="form.contactsMobile"/> -->
<Field
label="子区域数量"
prop="childSize"
v-model="form.childSize"
/>
<Field
label="子区域的最大ID"
prop="maxChildId"
v-model="form.maxChildId"
/>
<Field
label="是否启用"
prop="status"
v-model="form.status"
:enumData="dict.status"
type='select'
/>
<Field
label="描述"
prop="remark"
v-model="form.remark"
:span='24'
/>
</el-row>
<form-buttons @submit='submitForm' />
</el-form>
</layout-form>
</template>
<script>
import form from "@/assets/mixins/form";
import { treeCache } from "@/assets/utils/tree";
export default {
mixins: [form],
async created() {
this.treeData = await treeCache.getTree();
this.form.parentId = this.query.pid;
},
methods: {
afterRender() {
this.selectedTreeID = treeCache.getPid(this.form.parentId);
},
beforeSubmit(form) {
form.parentId = this.selectedTreeID.slice().pop();
return form;
},
treeSelected(val) {
console.log(val);
this.form.parentId = val.slice().pop();
}
},
data() {
return {
toString: ["level", "status"],
treeData: [],
selectedTreeID: [],
rules: {
name: [{ required: true, message: "请输入区域名称", trigger: "blur" }],
remark: [{validator: (rule, val, callback) => {
if (val && val.split("").length > 200) {
return callback(new Error('描述不得超过200字'))
}
callback();
}, trigger: ['change','blur']
},
],
}
};
}
};
</script>
<template>
<div class="page">
<LayoutTable :data='tableData' :config='tableConfig' />
</div>
</template>
<script>
import table from '@/assets/mixins/table';
export default {
mixins: [table],
data() {
return {
config: {
search: [
{
name: 'loginName',
type: 'text',
label: '登录名',
},
{
name: 'requestUrl',
type: 'text',
label: '请求地址',
},
],
columns: [
{
type: 'selection',
width: 60,
},
{
prop: 'id',
label: '序号',
},
{
prop: 'userName',
label: '用户名称',
},
{
prop: 'loginName',
label: '用户登录名',
},
{
prop: 'requestUrl',
label: '请求地址',
},
{
prop: 'content',
label: '操作内容',
},
{
prop: 'ip',
label: '操作IP地址',
},
{
prop: 'logDate',
label: '操作时间',
width: 140,
formatter: this.formatterDate
},
{
label: '操作',
width: 100,
formatter: (row)=> {
return (
<table-buttons row={row} onDel={this.toDel} noEdit/>
)
},
},
],
},
}
}
}
</script>
<template>
<layout-form>
<el-form
:model="form"
:loading="loading"
:rules="rules"
size='small'
label-width='100px'
ref="form"
>
<el-row>
<Field label="序号" prop="id" v-model="form.id"/>
<Field label="平台标识" prop="platformMark" v-model="form.platformMark"/>
<Field label="用户id" prop="userId" v-model="form.userId"/>
<Field label="用户名称" prop="userName" v-model="form.userName"/>
<Field label="用户登录名" prop="loginName" v-model="form.loginName"/>
<Field label="请求地址" prop="requestUrl" v-model="form.requestUrl"/>
<Field label="操作内容" prop="content" v-model="form.content" type='textarea' :span='24'/>
<Field label="操作IP地址" prop="ip" v-model="form.ip"/>
<Field label="操作时间" prop="logDate" v-model="form.logDate"/>
<Field label="操作类型" prop="operType" v-model="form.operType" :enumData='dict.operType' type='select' />
</el-row>
<form-buttons @submit='submitForm'/>
</el-form>
</layout-form>
</template>
<script>
import form from '@/assets/mixins/form';
export default {
mixins: [form],
data() {
return {
toString: ["operType"],
rules: {id: [{ required: true, message: '请输入序号', trigger: 'blur' },],
platformMark: [{ required: true, message: '请输入平台标识', trigger: 'blur' },],
userId: [{ required: true, message: '请输入用户id', trigger: 'blur' },],
content: [{ required: true, message: '请输入操作内容', trigger: 'blur' },],
ip: [{ required: true, message: '请输入操作IP地址', trigger: 'blur' },],
logDate: [{ required: true, message: '请输入操作时间', trigger: 'blur' },],
operType: [{ required: true, message: '请选择操作类型', trigger: 'blur' },]},
}
}
}
</script>
<template>
<div class="page">
<LayoutTable :data='tableData' :config='tableConfig' notPagination />
</div>
</template>
<script>
import table from '@/assets/mixins/table';
export default {
mixins: [table],
methods: {
beforeRender(data) {
this.allMenu = this.sortByGroup(this.util_copy(data.result));
// 存在查询条件,展开全部
if(Object.keys(this.$route.query).length) {
this.select = this.allMenu.filter(i=>!i.parentId).map(i=>i.id);
}
return data;
},
afterRender() {
this.showChild();
},
// 按parentId排序分组
sortByGroup(data) {
return data.filter(i=>!i.parentId).reduce((prev, item)=>{
return prev.concat([item], data.filter(i=>i.parentId == item.id));
}, [])
},
// 查看下级菜单
selectHandler({id}) {
// 如果已展开,则关闭
const index = this.select.indexOf(id);
if(index > -1) {
this.select.splice(index, 1);
}else{
this.select.push(id);
}
this.showChild();
},
showChild() {
this.tableData.result = this.allMenu.filter(item=>{
return !item.parentId || this.select.indexOf(item.parentId) > -1
});
},
// 展示菜单图标
showIcon(row, column) {
return <i class={'el-icon-'+row.imgPath}></i>
},
// 操作菜单状态
changeStatus(row, column) {
return (
<my-switch
confirm
url='/menu/save'
row={row}
onChange={this.statusChange}
value={this.tableData.result}
onInput={(data)=>{
this.tableData.result = data;
}}/>
)
},
afterDel(id) {
this.$store.dispatch('login');
},
statusChange() {
this.$store.dispatch('login');
},
},
data() {
return {
allMenu: [], // 经过分组排序的表格数据
select: [], // 当前展开的树节点
query: {
'pageInfo.prePageResult': -1
},
config: {
search: [
{
name: 'name',
type: 'text',
label: '菜单名称',
},
],
columns: [
{
type: 'selection',
width: 60,
},
{
width: 60,
formatter: row => {
const icon = this.select.indexOf(row.id) === -1 ? 'right' : 'down';
return (
!row.parentId
? <div onClick={()=>{this.selectHandler(row)}}>
<i class={'el-icon-arrow-'+icon}></i>
</div>
: ''
)
}
},
{
prop: 'id',
label: 'ID',
width: 60,
},
{
prop: 'name',
label: '名称',
width: 160,
},
{
prop: 'imgPath',
label: '图标',
width: 50,
formatter: this.showIcon,
},
{
prop: 'authType',
label: '权限类型',
formatter: this.formatter,
},
{
prop: 'parentId',
label: '父ID',
},
{
prop: 'url',
label: '地址',
},
{
prop: 'status',
label: '状态',
width: 100,
formatter: this.changeStatus,
},
{
label: '操作',
formatter: (row)=> {
return (
<table-buttons row={row} onEdit={this.toEdit} onDel={this.toDel} />
)
},
},
],
},
}
}
}
</script>
<template>
<layout-form>
<el-form
:model="form"
:loading="loading"
:rules="rules"
size='small'
label-width='100px'
ref="form"
>
<el-row>
<Field label="ID" prop="id" v-model="form.id" v-if='pageInfo.type !== "add"' disabled />
<Field label="名称" prop="name" v-model="form.name"/>
<Field label="权限类型" prop="authType" v-model="form.authType" :enumData='dict.authType' type='select' />
<Field label="父级菜单" prop="parentId" v-model="form.parentId" :enumData='menu' type='select' />
<Field label="访问地址" prop="url" v-model="form.url" />
<Field label="状态" prop="status" v-model="form.status" :enumData='dict.status' type='radio' />
<Field label="图标" prop="imgPath" :span='24'>
<el-radio-group v-model="form.imgPath" class='form-el-radio-group'>
<el-radio-button label="">不需要图标</el-radio-button>
<el-radio-button v-for='(icon, index) in icons' :key='index' :label="icon">
<i :class="'el-icon-'+icon"></i>
{{icon}}
</el-radio-button>
</el-radio-group>
</Field>
</el-row>
<form-buttons @submit='submitForm'/>
</el-form>
</layout-form>
</template>
<script>
import form from '@/assets/mixins/form';
export default {
mixins: [form],
methods: {
afterSubmit() {
this.$store.dispatch('login');
this.$router.go(-1);
},
},
computed: {
menu() {
let menu = {'0': ''};
this.$store.state.userData.barList.forEach(item=>{
menu[item.id+''] = item.name
});
return menu;
}
},
data() {
return {
toString: ['parentId', 'authType', 'status'],
icons: [
'info', 'error', 'success', 'warning', 'question',
'tickets', 'document', 'goods', 'sold-out', 'news',
'message', 'date', 'printer', 'time', 'bell',
'mobile-phone', 'service', 'view', 'menu', 'star-on',
'location', 'phone', 'picture', 'delete', 'search',
'edit', 'rank', 'refresh', 'share', 'setting',
'upload', 'upload2', 'download', 'loading',
],
rules: {
name: [
{ required: true, message: '请输入名称', trigger: 'blur' },
],
},
}
}
}
</script>
<template>
<div class="page">
<LayoutTable :data='tableData' :config='tableConfig' />
</div>
</template>
<script>
import table from '@/assets/mixins/table';
export default {
mixins: [table],
data() {
return {
config: {
search: [
{
name: 'name',
type: 'text',
label: '参数名称',
},
],
columns: [
{
type: 'selection',
width: 60,
},
{
prop: 'name',
label: '参数名称',
},
{
prop: 'firstOrganize',
label: '一级组织',
},
{
prop: 'secondOrganize',
label: '二级组织',
},
{
prop: 'paramKey',
label: '参数键',
},
{
prop: 'paramValue',
label: '参数值',
// formatter: this.util_short('paramValue', 20)
},
{
prop: 'validStatus',
label: '有效状态',
width: 70,
formatter: this.formatter
},
{
prop: 'modStatus',
label: '修改状态',
width: 100,
formatter: this.formatter
},
{
prop: 'displayType',
label: '展现类型',
width: 100,
formatter: this.formatter
},
{
prop: 'remark',
label: '备注',
},
{
label: '操作',
width: 180,
formatter: (row)=> {
return (
<table-buttons row={row} onEdit={this.toEdit} onView={this.toView} onDel={this.toDel} />
)
},
},
],
},
}
}
}
</script>
<style lang="css">
.el-tooltip__popper{
display: inline-block;
max-width: 80%;
overflow: hidden;
text-overflow: ellipsis;
white-space: normal ;
line-height: 18px;
cursor: pointer;
}
</style>
<template>
<layout-form>
<el-form
:model="form"
:loading="loading"
:rules="rules"
size='small'
label-width='100px'
ref="form"
>
<el-row>
<Field label="参数名称" prop="name" v-model="form.name"/>
<Field label="一级组织" prop="firstOrganize" v-model="form.firstOrganize"/>
<Field label="二级组织" prop="secondOrganize" v-model="form.secondOrganize"/>
<Field label="参数有效状态" prop="validStatus" v-model="form.validStatus" :enumData='dict.validStatus' type='select' />
<Field label="参数修改状态" prop="modStatus" v-model="form.modStatus" :enumData='dict.modStatus' type='select' />
<Field label="展现类型" prop="displayType" v-model="form.displayType" :enumData='dict.displayType' type='select' />
<Field label="参数键" prop="paramKey" v-model="form.paramKey" :span='24'/>
<Field label="参数值" prop="paramValue" v-model="form.paramValue" :span='24' type="textarea"/>
<Field label="备注" prop="remark" v-model="form.remark" :span='24'/>
</el-row>
<form-buttons @submit='submitForm'/>
</el-form>
</layout-form>
</template>
<script>
import form from '@/assets/mixins/form';
export default {
mixins: [form],
data() {
return {
toString: ['validStatus', 'modStatus', 'displayType'],
rules: {
name: [{ required: true, message: '请输入参数名称', trigger: 'blur' },],
paramKey: [{ required: true, message: '请输入参数键', trigger: 'blur' },],
paramValue: [{ required: true, message: '请输入参数值', trigger: 'blur' },],
},
}
}
}
</script>
<template>
<div class="page">
<LayoutTable :data='tableData' :config='tableConfig' />
</div>
</template>
<script>
import table from '@/assets/mixins/table';
export default {
mixins: [table],
data() {
return {
config: {
search: [
{
name: 'name',
type: 'text',
label: '资源名称',
},
{
name: 'authType',
type: 'select',
label: '权限类型',
},
],
columns: [
{
type: 'selection',
width: 60,
},
{
prop: 'id',
label: 'ID',
width: 60,
},
{
prop: 'name',
label: '名称',
},
{
prop: 'url',
label: '资源',
},
{
prop: 'authType',
label: '认证类型',
width: 140,
formatter: this.formatter,
},
// {
// prop: 'userType',
// label: '用户类型',
// width: 100,
// formatter: this.formatter,
// },
{
label: '操作',
witdh: 120,
formatter: (row)=> {
return (
<table-buttons row={row} onEdit={this.toEdit} onDel={this.toDel} />
)
},
},
],
},
}
}
}
</script>
<template>
<layout-form>
<el-form
:model="form"
:loading="loading"
:rules="rules"
size='small'
label-width='100px'
ref="form"
>
<el-row>
<Field label="名称" prop="name" v-model="form.name" />
<Field label="权限类型" prop="authType" v-model="form.authType" :enumData='dict.authType' type='select' />
<!-- <Field label="用户类型" prop="userType" v-model="form.userType" :enumData='dict.userType' type='select' /> -->
<Field label="链接地址" prop="url" :span='24'>
<el-button icon="el-icon-plus" circle size='mini' @click='add' v-if='!form.urls.length'></el-button>
<el-row v-for='(url, index) in form.urls' :key='index' style="width: 400px">
<el-col :span='16'>
<el-form-item label-width="0"
:prop="'urls.'+ index +'.value'"
:rules="[
{required: true, message: '地址不能为空', trigger: 'blur'},
{validator: validatorUrl, trigger: 'blur'}
]"
>
<el-input size='mini' v-model="url.value"></el-input>
</el-form-item>
</el-col>
<el-col :span='8'>
&nbsp;
<el-button icon="el-icon-minus" circle size='mini' @click='del(index)'></el-button>
<el-button icon="el-icon-plus" circle size='mini' @click='add' v-if='index === form.urls.length-1'></el-button>
</el-col>
</el-row>
</Field>
</el-row>
<form-buttons @submit='submitForm'/>
</el-form>
</layout-form>
</template>
<script>
import form from '@/assets/mixins/form';
import FormButtons from '@/components/tools/FormButtons';
export default {
mixins: [form],
components: {
FormButtons,
},
methods: {
beforeRender(data) {
data.entity.urls = (data.entity.url || '').split(',').map(i=>{return {value: i}});
return data;
},
beforeSubmit(form){
this.form.url = this.form.urls.map(item=>item.value).join(',');
return this.form;
},
del(index){
this.form.urls.splice(index, 1);
},
add(index){
const urls = this.form.urls;
const values = urls.map(i=>i.value);
// 新增前检查前方是否有空行
if(urls.some(i=>!i.value)){
return this.$message.warning('请先完成上一个地址的填写')
}
urls.push({value: ''})
},
isRepeat(value) {
return this.form.urls.filter(i=>value == i.value).length > 1;
},
validatorUrl(rule, value, cb) {
if(this.isRepeat(value)){
return cb(new Error(`重复的url地址`));
}
cb();
},
},
data() {
return {
toString: ['userType', 'authType'],
form: {
urls: [],
},
rules: {
name: [
{ required: true, message: '请输入名称', trigger: 'blur' },
]
},
}
}
}
</script>
<template>
<div class="page">
<LayoutTable :data='tableData' :config='tableConfig' />
<el-dialog title="分配权限" :visible.sync="auth.visible">
<el-form :model="auth.form">
<el-checkbox-group v-model="auth.checkList">
<div v-for='(group, key) in allResources' :key='key'>
<h2 style="font-size: 14px;font-weight: bold;margin: 10px 0">
{{key}}
<el-checkbox :key='key' @change='(e)=>{handleChange(e, key)}' :label="key">全选</el-checkbox>
</h2>
<el-checkbox v-for='item in group.list' :key='item.id' :label="item.id">
{{item.name}}
</el-checkbox>
</div>
</el-checkbox-group>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button size='mini' @click="auth.visible = false">取 消</el-button>
<el-button size='mini' type="primary" @click="saveAuth">确 定</el-button>
</div>
</el-dialog>
<div class="userSaveDiv">
<el-dialog title="分配用户" :visible.sync="user.visible" width="75%">
<el-form :model="user.form" size='mini' label-width='80px' >
<el-row>
<el-col :span='8'>
<span>用户类型:</span>
<el-select placeholder="请选择用户类型" v-model="userTypeIdVal" size='mini' clearable>
<el-option
v-for='($label, $value) in userTypeMap'
:key='$value'
:label="$label"
:value="$value">
</el-option>
</el-select>
</el-col>
<Field label="登录账号" prop="loginNameVal" v-model="loginNameVal" placeholder="请输入登录账号" :span='8'/>
<Field label="昵称" prop="realNameVal" v-model="realNameVal" placeholder="请输入昵称" :span='8'/>
<el-col style="text-align:center">
<el-button type="primary" size='mini' icon='el-icon-search' @click="searchUserList">查询未分配用户</el-button>
<el-button icon='search' size='mini' plain @click="cleanSearchCon">清空</el-button>
</el-col>
</el-row>
<fieldset class="check-user-fieldset">
<legend>已分配用户</legend>
<div style="margin-left:15px;margin-bottem:10px;height:90%;overflow:auto;">
<el-checkbox-group v-model="user.checkList" style="margin-left:15px;margin-bottem:10px;">
<el-checkbox v-for='item in checkedUsers' @change='(e)=>{handleUnCheckChangeUser(e, item)}' :key='item.id' :label="item.id" :name="item.realName">{{item.realName}}</el-checkbox>
</el-checkbox-group>
</div>
</fieldset>
<fieldset class="check-user-fieldset">
<legend>未分配用户</legend>
<div style="margin-left:15px;margin-bottem:10px;height:90%;overflow:auto;">
<el-checkbox-group v-model="user.checkList" style="margin-left:15px;margin-bottem:10px;">
<el-checkbox v-for='item in unCheckedUsers' @change='(e)=>{handleCheckChangeUser(e, item)}' :key='item.id' :label="item.id">{{item.realName}}</el-checkbox>
</el-checkbox-group>
</div>
</fieldset>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button size='mini' @click="user.visible = false">取 消</el-button>
<el-button size='mini' type="primary" @click="saveUser">确 定</el-button>
</div>
</el-dialog>
</div>
</div>
</template>
<style>
.userSaveDiv .el-dialog {
margin: 0 auto !important;
height: 100%;
overflow: hidden;
margin-bottom: 400px
}
.userSaveDiv .el-dialog__body {
position: absolute;
left: 50PX;
top: 54px;
bottom: 50PX;
right: 0;
padding: 0;
z-index: 1;
overflow: hidden;
overflow-y: auto;
}
.userSaveDiv .el-dialog__footer {
position: absolute;
bottom: 0;
right: 0;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
.userSaveDiv .check-user-fieldset{
height:480px;
border: 1px solid #ededed;
float: left;
margin-left:1%;
width: 48%;
margin-top: 20px;
}
</style>
<script>
import table from '@/assets/mixins/table';
export default {
mixins: [table],
created() {
},
methods: {
beforeRender(data) {
this.customerMap = data.dict.customerId;
this.userTypeMap = data.dict.userType;
return data;
},
// 打开弹窗,获取已经选中的权限
async setAuth({id}) {
this.tableData.loading = true;
try {
this.auth.form = this.initForm();
this.allResources = await this.getAuths();
this.auth.checkList = await this.getRoleAuths(id);
this.auth.form.roleId = id;
this.auth.visible = true;
} catch (error) {
this.$message.error(error.message);
}
this.tableData.loading = false;
},
// 获取权限列表
getAuths() {
if(Object.keys(this.allResources).length) {
return this.allResources;
}
return new Promise((resolve, reject)=>{
this.$post('/resource/list', {pageInfo: {prePageResult: -1}}).then(({data})=>{
resolve(this.groupByAuth(data.result));
}).catch(reject)
})
},
// 权限分组
groupByAuth(list) {
let group = {};
list.forEach(item=>{
let name = item.name.split('-')[0];
if(!group[name]) {
group[name] = {
selectAll: false,
list: [],
};
}
group[name].list.push(item);
})
return group;
},
// 选中权限组
handleChange(checked, type) {
const list = this.auth.checkList.slice();
const selectd = this.allResources[type].list.map(i=>i.id);
if(checked) {
this.auth.checkList = [...new Set(list.concat(selectd))];
}else{
this.auth.checkList = this.auth.checkList.filter(i=>selectd.indexOf(i) === -1)
}
},
// 获取角色权限列表
getRoleAuths(id) {
return new Promise((resolve, reject)=>{
this.$post('/role/auth/list', {'query.roleId': id, 'pageInfo.prePageResult': -1}).then(({data})=>{
const result = data.result.map(i=>i.resourceId);
resolve(result);
}).catch(reject)
})
},
// 保存选中的权限
async saveAuth() {
try {
this.auth.form.resourceIdList = this.auth.checkList.filter(i=>typeof i === 'number').join(',');
await this.$post('/role/auth/distributionSource', {query: this.auth.form});
this.auth.visible = false;
this.auth.form = this.initForm();
this.$message.success('操作成功');
} catch (error) {
this.$message.error(error.message);
}
},
// 获取用户列表
getUsers() {
// if(this.allUsers.length) {
// return this.allUsers;
// }
return new Promise((resolve, reject)=>{
this.$post('/user/list', {pageInfo: {prePageResult: -1}}).then(({data})=>{
resolve(data.result);
}).catch(reject)
})
},
async searchUserList(){
this.allUsers = await this.getUsersoo(this.userTypeIdVal,this.loginNameVal,this.realNameVal);
this.unCheckedUsers=[];
if(this.allUsers && this.allUsers.length>0){
this.allUsers.forEach((item, i)=>{
if(!this.user.checkList.includes(item.id)){
this.unCheckedUsers.push(item);
}
})
}
},
async getUsersoo(userTypeIdVal,loginNameVal,realNameVal){
const query = {'pageInfo.prePageResult': -1,'query.userType':userTypeIdVal,'query.loginName':loginNameVal,'query.realName':realNameVal};
return new Promise((resolve, reject)=>{
this.$post('/user/list', query).then(({data})=>{
resolve(data.result);
}).catch(reject)
})
},
cleanSearchCon(){
this.loginNameVal="";
this.userTypeIdVal="";
this.realNameVal="";
},
handleCheckChangeUser(checked, item) {
var checkUserId = item.id;
if(checked) {
var tempItem = {};
tempItem.id = checkUserId;
tempItem.realName = item.realName;
this.user.checkList.push(checkUserId);
this.checkedUsers.push(tempItem);
this.unCheckedUsers = this.unCheckedUsers.filter(i=>i.id != checkUserId);
this.user.checkList = [...new Set(this.user.checkList)];
}
},
handleUnCheckChangeUser(checked, item) {
var checkUserId = item.id;
if(!checked) {
var tempItem = {};
tempItem.id = checkUserId;
tempItem.realName = item.realName;
this.unCheckedUsers.push(tempItem);
this.user.checkList = this.user.checkList.filter(i=>i.id != checkUserId);
this.checkedUsers = this.checkedUsers.filter(i=>i.id != checkUserId);
}
},
// 获取角色用户列表
getRoleUsers(id) {
return new Promise((resolve, reject)=>{
this.$post('/role/user/list', {'query.roleId': id, 'pageInfo.prePageResult': -1}).then(({data})=>{
const result = data.result.filter(i=>i.userId).map(i=>i.userId);
this.resultUserDict = data.dict.userReNameMap;
if(data.result && data.result.length>0){
data.result.forEach(i=>{
var tempItem = {};
tempItem.id = i.userId;
tempItem.realName = (this.resultUserDict[i.userId] || i.userId);
this.checkedUsers.push(tempItem);
})
}
resolve(result);
}).catch(reject)
})
},
// 打开弹窗
async setUser({id}) {
try {
this.cleanSearchCon();
this.tableData.loading = true;
this.user.form = this.initUserForm();
// this.allUsers = await this.getUsers();
this.checkedUsers=[];
this.user.checkList = await this.getRoleUsers(id);
this.user.form.roleId = id;
this.user.visible = true;
this.unCheckedUsers=[];
} catch (error) {
this.$message.error(error.message);
}
this.tableData.loading = false;
},
// 保存选中的用户
async saveUser() {
try {
this.user.form.userIdList = this.user.checkList.join(',');
await this.$post('/role/user/distributionUser', {query: this.user.form})
this.user.visible = false;
this.user.form = this.initForm();
this.$message.success('操作成功');
} catch (error) {
this.$message.error(error.message);
}
},
initForm() {
return {
resourceIdList: '',
roleId: '',
}
},
initUserForm() {
return {
userIdList: '',
roleId: '',
}
},
},
data() {
return {
customerMap:[],
userTypeMap:[],
allResources: {},
allUsers: {},
checkedUsers:[],
unCheckedUsers:[],
resultUserDict:[],
realNameVal:"",
loginNameVal:"",
userTypeIdVal:"",
user: {
visible: false,
checkList: [],
form: this.initUserForm(),
},
auth: {
visible: false,
checkList: [],
form: this.initForm(),
},
config: {
search: [
{
name: 'name',
type: 'text',
label: '角色名',
},
{
name: 'roleType',
type: 'select',
label: '角色类型',
},
],
columns: [
{
type: 'selection',
width: 60,
},
{
prop: 'id',
label: 'ID',
width: 60,
},
{
prop: 'name',
label: '角色名',
},
{
prop: 'roleType',
label: '角色类型',
width: 130,
formatter: this.formatter,
},
{
prop: 'createTime',
label: '创建时间',
width: 160,
formatter: this.formatterDate,
},
{
prop: 'remark',
label: '备注',
},
{
label: '操作',
witdh: 380,
formatter: (row)=> {
return (
<div>
<table-buttons row={row} onEdit={this.toEdit} onDel={this.toDel} />
{' '}
<el-tooltip content="分配权限" placement="top">
<el-button icon="el-icon-share" circle size='mini' onClick={()=>this.setAuth(row)}></el-button>
</el-tooltip>
<el-tooltip content="分配用户" placement="top">
<el-button icon="el-icon-goods" circle size='mini' onClick={()=>this.setUser(row)}></el-button>
</el-tooltip>
</div>
)
},
},
]
},
}
}
}
</script>
<template>
<layout-form>
<el-form
:model="form"
:loading="loading"
:rules="rules"
size='small'
label-width='100px'
ref="form"
>
<el-row>
<Field label="角色名" prop="name" v-model="form.name" />
<Field label="角色类型" prop="roleType" v-model="form.roleType" :enumData='dict.roleType' type='select' />
<Field label="备注" prop="remark" v-model="form.remark" type='textarea' :span='24'/>
</el-row>
<form-buttons @submit='submitForm'/>
</el-form>
</layout-form>
</template>
<script>
import form from '@/assets/mixins/form';
export default {
mixins: [form],
data() {
return {
toString: ['roleType'],
rules: {
name: [
{ required: true, message: '请输入名称', trigger: 'blur' },
],
roleType: [
{ required: true, message: '请选择用户类型', trigger: 'blur' },
],
},
}
}
}
</script>
<template>
<div class="page">
<el-form
:model="queryParams"
ref="queryForm"
:inline="true"
v-show="showSearch"
>
<el-form-item label="站点名称" prop="siteName">
<el-input
v-model="queryParams['query.siteName']"
placeholder="请输入站点名称"
clearable
size="small"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item>
<el-button
type="primary"
icon="el-icon-search"
size="mini"
@click="handleQuery"
>搜索</el-button
>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery"
>重置</el-button
>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="primary"
plain
icon="el-icon-plus"
size="mini"
@click="handleAdd"
>新增</el-button
>
</el-col>
<right-toolbar
:showSearch.sync="showSearch"
@queryTable="getList"
></right-toolbar>
</el-row>
<el-table
v-loading="loading"
:data="siteList"
row-key="id"
border
default-expand-all
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
>
<el-table-column
prop="siteName"
label="站点名称"
width="400"
></el-table-column>
<el-table-column
prop="number"
label="站点编号"
width="200"
></el-table-column>
<el-table-column
prop="address"
label="站点地址"
width="200"
></el-table-column>
<el-table-column
prop="status"
label="状态"
:formatter="statusFormat"
width="100"
></el-table-column>
<el-table-column
label="创建时间"
align="center"
prop="createTime"
width="200"
>
<template slot-scope="scope">
<span>{{ formatterDate(scope.row.createTime) }}</span>
</template>
</el-table-column>
<el-table-column
label="操作"
>
<template slot-scope="scope">
<el-button
size="mini"
type="text"
icon="el-icon-edit"
@click="handleUpdate(scope.row)"
>修改</el-button
>
<el-button
size="mini"
type="text"
icon="el-icon-plus"
@click="handleAdd(scope.row)"
>新增</el-button
>
<el-button
v-if="scope.row.parentId != 0"
size="mini"
type="text"
icon="el-icon-delete"
@click="handleDelete(scope.row)"
>删除</el-button
>
</template>
</el-table-column>
</el-table>
<!-- 添加或修改站点对话框 -->
<el-dialog :title="title" :visible.sync="open" width="70%" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
<el-row>
<el-col :span="24" v-if="form.parentId !== 0">
<el-form-item label="上级站点" prop="parentId">
<treeselect
v-model="form.parentId"
:options="siteOptions"
:normalizer="normalizer"
placeholder="选择上级站点"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="站点名称" prop="siteName">
<el-input v-model="form.siteName" placeholder="请输入站点名称" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="显示排序" prop="orderNum">
<el-input-number
v-model="form.orderNum"
controls-position="right"
:min="0"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="地址" prop="address">
<el-input
v-model="form.address"
placeholder="请输入地址"
maxlength="20"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="联系电话" prop="mobile">
<el-input
v-model="form.mobile"
placeholder="请输入联系电话"
maxlength="11"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="站点编号" prop="number">
<el-input
v-model="form.number"
placeholder="请输入站点编号"
maxlength="50"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="站点状态">
<!-- <el-radio-group v-model="form.status">
<el-radio
v-for="(label, value) in dict.status"
:key="value"
:label="value"
>{{ label }}</el-radio
>
</el-radio-group> -->
<mu-flex
align-items="center"
style="width: 100%"
:key="value"
v-for="(label, value) in dict.status"
>
<mu-radio
style="font-size: 14px"
:value="value"
v-model="form.status"
:label="label"
></mu-radio>
</mu-flex>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="单位介绍" prop="introduce">
<el-input
v-model="form.introduce"
placeholder="请输入单位介绍"
type="textarea"
:rows="2"
/>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="中心介绍" prop="summary">
<el-input
v-model="form.summary"
placeholder="请输入中心介绍"
type="textarea"
:rows="2"
/>
</el-form-item>
</el-col>
</el-row>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitForm">确 定</el-button>
<el-button @click="cancel">取 消</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { handleTree, formatterDate } from "@/assets/utils";
import Treeselect from "@riophae/vue-treeselect";
import "@riophae/vue-treeselect/dist/vue-treeselect.css";
export default {
name: "Dept",
components: { Treeselect },
data() {
return {
// 遮罩层
loading: true,
// 显示搜索条件
showSearch: true,
// 表格树数据
siteList: [],
// 站点树选项
siteOptions: [],
// 弹出层标题
title: "",
// 是否显示弹出层
open: false,
// 状态数据字典
statusOptions: [],
// 查询参数
queryParams: {
"query.siteName": null,
},
// 表单参数
form: {},
dict: {},
toString: ["status"],
// 表单校验
rules: {
parentId: [
{ required: true, message: "上级站点不能为空", trigger: "blur" },
],
siteName: [
{ required: true, message: "站点名称不能为空", trigger: "blur" },
],
orderNum: [
{ required: true, message: "显示排序不能为空", trigger: "blur" },
],
email: [
{
type: "email",
message: "'请输入正确的邮箱地址",
trigger: ["blur", "change"],
},
],
mobile: [
{
pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/,
message: "请输入正确的手机号码",
trigger: "blur",
},
],
},
};
},
created() {
this.getList();
},
methods: {
formatterDate(time) {
return formatterDate(time);
},
/** 查询站点列表 */
getList() {
this.loading = true;
let query = {};
//判断追加百分号
Object.assign(query, this.queryParams);
if (query["query.siteName"] != null) {
query["query.siteName"] = "%" + query["query.siteName"] + "%";
}
this.$post("/site/list", query)
.then((res) => {
if (res && res.code && res.code == 1) {
this.siteList = handleTree(res.data.result, "id");
this.dict = Object.assign({}, this.dict, res.data.dict);
this.loading = false;
}
})
.catch((error) => {
this.$message.error(error.message);
});
},
/** 转换站点数据结构 */
normalizer(node) {
console.log("normalizer", node);
if (node.children && !node.children.length) {
delete node.children;
}
return {
id: node.id,
label: node.siteName,
children: node.children,
};
},
// 字典状态字典翻译
statusFormat(row, column) {
try {
return this.dict["status"][row.status];
} catch (error) {
return row.status;
}
},
// 取消按钮
cancel() {
this.open = false;
this.reset();
},
resetForm(refName) {
if (this.$refs[refName]) {
this.$refs[refName].resetFields();
}
},
// 表单重置
reset() {
this.form = {
id: null,
parentId: 0,
siteName: "",
orderNum: 0,
address: "",
mobile: "",
introduce: "",
summary: "",
ancestors: "",
status: "1",
};
this.resetForm("form");
},
/** 搜索按钮操作 */
handleQuery() {
this.getList();
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm("queryForm");
this.handleQuery();
},
/** 新增按钮操作 */
handleAdd(row) {
this.reset();
if (row.id != undefined) {
this.form.parentId = row.id;
}
this.open = true;
this.title = "添加站点";
this.loading = true;
this.$post("/site/list", {})
.then((res) => {
if (res && res.code && res.code == 1) {
this.siteOptions = handleTree(res.data.result);
this.loading = false;
}
})
.catch((error) => {
this.$message.error(error.message);
});
},
/** 修改按钮操作 */
handleUpdate(row) {
this.reset();
this.loading = true;
this.$post("/site/edit", { id: [row.id] })
.then((res) => {
if (res && res.code && res.code == 1) {
res.data.entity = this.util_toString(
res.data.entity,
this.toString
);
Object.assign(this.form, res.data.entity);
this.open = true;
this.title = "修改站点";
this.loading = false;
}
})
.catch((error) => {
this.$message.error(error.message);
});
this.$post("/site/list/exclude", { id: [row.id] })
.then((res) => {
if (res && res.code && res.code == 1) {
this.siteOptions = handleTree(res.data.result);
}
})
.catch((error) => {
this.$message.error(error.message);
});
},
/** 提交按钮 */
submitForm: function () {
this.loading = true;
const el = this.$refs.form;
el.validate((valid) => {
if (!valid) return;
this.$post("/site/save", {
entity: this.form,
})
.then((res) => {
if (res && res.code && res.code == 1) {
this.loading = false;
this.reset();
this.open = false;
this.getList();
}
})
.catch((error) => {
this.loading = false;
this.$message.error(error.message);
});
});
},
/** 删除按钮操作 */
handleDelete(row) {
let _this=this
this.$confirm(
'是否确认删除名称为"' + row.siteName + '"的数据项?',
"警告",
{
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
}
).then(function () {
_this.$post("/site/delete", { id: [row.id] })
.then((res) => {
if (res && res.code && res.code == 1) {
_this.getList();
_this.$message.success("删除成功");
}
})
.catch((error) => {
_this.$message.error(error.message);
});
});
},
// 工具方法,把数字转化为字符串
util_toString(data, array) {
const dataCopy = Object.assign({}, data);
array.forEach((item) => {
dataCopy[item] =
dataCopy[item] === undefined ? "" : dataCopy[item] + "";
});
return dataCopy;
},
},
};
</script>
\ No newline at end of file
<template>
<div class="page">
<LayoutTable :data='tableData' :config='tableConfig' />
</div>
</template>
<script>
import table from '@/assets/mixins/table';
export default {
mixins: [table],
data() {
return {
config: {
search: [
{
name: 'name',
type: 'text',
label: '任务名称',
},
{
name: 'status',
type: 'select',
label: '任务状态',
},
],
columns: [
{
type: 'selection',
width: 60,
},
{
prop: 'name',
label: '任务名称',
},
{
prop: 'excuteHost',
label: '执行主机',
},
{
prop: 'excuteContainer',
label: '执行容器',
},
{
prop: 'excuteStrategy',
label: '执行策略',
formatter: this.formatter
},
{
prop: 'lastExcuteHost',
label: '最后执行主机',
},
{
prop: 'lastExcuteTime',
label: '最后执行时间',
formatter: this.formatterDate
},
{
prop: 'status',
label: '执行状态',
formatter: this.formatter
},
{
label: '操作',
width: 180,
formatter: (row)=> {
return (
<table-buttons row={row} onEdit={this.toEdit} onDel={this.toDel} />
)
},
},
],
},
}
}
}
</script>
<template>
<layout-form>
<el-form
:model="form"
:loading="loading"
:rules="rules"
size='small'
label-width='120px'
ref="form"
>
<el-row>
<Field label="任务名称" prop="name" v-model="form.name"/>
<Field label="关键字" prop="taskKey" v-model="form.taskKey"/>
<Field label="执行服务" prop="excuteService" v-model="form.excuteService" :enumData='dict.excuteService' type='select' />
<Field label="执行策略" prop="excuteStrategy" @change='excuteStrategyChange' v-model="form.excuteStrategy" :enumData='dict.excuteStrategy' type='select' />
<Field :label="form.excuteStrategy == 4 ? '执行间隔时间' : '执行日期'" prop="excuteDate">
<el-input disabled value='每天' v-if='form.excuteStrategy == 1'></el-input>
<el-select v-model="form.excuteDate" v-if='form.excuteStrategy == 2'>
<el-option
v-for='($label, $value) in dict.week'
:key='$value'
:label="$label"
:value="$value"
></el-option>
</el-select>
<el-select v-model="form.excuteDate" v-if='form.excuteStrategy == 3'>
<el-option
v-for='($label, $value) in dict.days'
:key='$value'
:label="$label"
:value="$value"
></el-option>
</el-select>
<el-input v-model="form.excuteDate" v-if='form.excuteStrategy == 4'>
<template slot="append"></template>
</el-input>
</Field>
<Field label="执行时间" prop="excuteTime" v-if='form.excuteStrategy != 4'>
<el-time-select
v-model="form.excuteTime"
:picker-options="{
start: '00:00',
step: '00:5',
end: '23:45'
}"
placeholder="选择时间">
</el-time-select>
</Field>
<Field label="执行主机" prop="excuteHost" v-model="form.excuteHost"/>
<Field label="执行参数" prop="excuteParam" v-model="form.excuteParam" :span='24' type='textarea' textareaSize/>
<Field label="备注" prop="remark" v-model="form.remark" :span='24' type='textarea' textareaSize/>
</el-row>
<form-buttons @submit='submitForm'/>
</el-form>
</layout-form>
</template>
<script>
import form from '@/assets/mixins/form';
export default {
mixins: [form],
methods: {
afterRender(data) {
},
beforeRender(data) {
data.dict = data.dict || {};
const days = {};
[...new Array(31)].forEach((i,index)=>{
let key = index+1;
days[key] = `${key}号`;
})
data.dict.days = days;
data.dict.week = {
1: '星期一',
2: '星期二',
3: '星期三',
4: '星期四',
5: '星期五',
6: '星期六',
7: '星期天',
};
data.dict.excuteService = data.excuteService;
return data;
},
excuteStrategyChange(val) {
this.form.excuteDate = val == 1 ? '0' : '1';
}
},
data() {
return {
toString: ['excuteService', 'excuteStrategy', 'excuteDate'],
rules: {
name: [{ required: true, message: '请输入任务名称', trigger: 'blur' },],
taskKey: [{ required: true, message: '请输入任务关键字', trigger: 'blur' },],
excuteService: [{ required: true, message: '请选择任务执行服务', trigger: 'blur' },],
},
}
}
}
</script>
<template>
<div class="page">
<LayoutTable :data='tableData' :config='tableConfig' notDel />
<el-dialog title="用户已分配的角色" :visible.sync="role.visible">
<el-form :model="role.form">
<el-checkbox-group v-model="role.checkList" :min='500'>
<el-checkbox v-for='item in allRoles' :key='item.id' :label="item.id">{{item.name}}</el-checkbox>
</el-checkbox-group>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button size='mini' @click="role.visible = false">关闭</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import table from "@/assets/mixins/table";
export default {
mixins: [table],
methods: {
// 打开弹窗
async findRole({id}) {
try {
this.tableData.loading = true;
this.allRoles = await this.getUserRoles(id);
this.role.checkList = await this.getRoleUsers(id);
this.role.visible = true;
} catch (error) {
this.$message.error(error.message);
}
this.tableData.loading = false;
},
// 获取用户角色列表
getUserRoles(id) {
return new Promise((resolve, reject)=>{
this.$post('/role/roleNameByUserId', {'userId': id}).then(({data})=>{
resolve(data);
}).catch(reject)
})
},
getRoleUsers(id) {
return new Promise((resolve, reject)=>{
this.$post('/role/user/list', {'query.userId': id, 'pageInfo.prePageResult': -1}).then(({data})=>{
const result = data.result.filter(i=>i.roleId).map(i=>i.roleId);
resolve(result);
}).catch(reject)
})
},
},
data() {
return {
allRoles: {},
role: {
checkList: [],
visible: false,
},
config: {
columns: [
{
type: "selection",
width: 60
},
{
prop: "id",
label: "ID",
width: 60
},
{
prop: "loginName",
label: "登录名称"
},
{
prop: "realName",
label: "昵称"
},
{
prop: "mobile",
label: "手机号码"
},
{
prop: "siteName",
label: "所属站点"
},
{
prop: "userType",
label: "用户类型",
width: 130,
formatter: this.formatter
},
{
prop: "status",
label: "状态",
width: 60,
formatter: this.formatter
},
{
label: "操作",
width: 220,
formatter: row => {
return (
<div>
<table-buttons row={row} onEdit={this.toEdit} onDel={this.toDel} noDel/>
<el-button round size='mini' type="info" icon="el-icon-tickets" onClick={()=>this.findRole(row)}>已分配的角色</el-button>
</div>
);
}
}
],
search: [
{
name: "loginName",
type: "text",
label: "登录名"
},
{
name: "realName",
type: "text",
label: "昵称"
},
{
name: "mobile",
type: "text",
label: "手机号"
},
{
name: "status",
type: "select",
label: "用户状态"
},
{
name: "userType",
type: "select",
label: "用户类型"
}
]
}
};
}
};
</script>
// 用户管理
<template>
<layout-form>
<el-form
:model="form"
:loading="loading"
:rules="rules"
size='small'
label-width='100px'
ref="form"
>
<el-row>
<Field label="登录名称" prop="loginName" v-model="form.loginName" />
<Field label="登录密码" prop="loginPwd" v-model="form.loginPwd" v-if='pageInfo.type === "add"' />
<Field label="用户昵称" prop="realName" v-model="form.realName" />
<Field label="手机号码" prop="mobile" v-model="form.mobile" />
<Field label="用户类型" prop="userType" v-model="form.userType" :enumData='dict.userType' type='select' />
<Field label="用户状态" prop="status" v-model="form.status" :enumData='dict.status' type='select' />
<el-col :span="12">
<el-form-item label="归属站点" prop="siteId">
<treeselect v-model="form.siteId" :options="siteOptions" :show-count="true" placeholder="请选择归属站点" />
</el-form-item>
</el-col>
</el-row>
<form-buttons @submit='submitForm'/>
</el-form>
</layout-form>
</template>
<script>
import form from '@/assets/mixins/form';
import Treeselect from "@riophae/vue-treeselect";
import "@riophae/vue-treeselect/dist/vue-treeselect.css";
export default {
mixins: [form],
name: "User",
components: { Treeselect },
created() {
//this.getList();
this.getTreeselect();
},
methods: {
/** 查询部门下拉树结构 */
getTreeselect() {
this.loading = true;
this.$post("/site/treeselect", {})
.then((res) => {
if (res && res.code && res.code == 1) {
this.siteOptions = res.data.result;
this.loading = false;
}
})
.catch((error) => {
this.$message.error(error.message);
});
},
},
data() {
return {
toString: ['status', 'userType'],
siteOptions:[],
rules: {
loginName: [
{ required: true, message: '请输入登录名称', trigger: 'blur' },
],
loginPwd: [
{ required: true, message: '请输入登录密码', trigger: 'blur' },
],
realName: [
{ required: true, message: '请输入用户昵称', trigger: 'blur' },
],
mobile: [
{ required: true, message: '请输入手机号码', trigger: 'blur' },
{ required: true, validator: (rule, val, cb)=>{
if(!/^1[0-9]{10}$/.test(val)){
return cb(new Error('手机号码格式不正确'))
}
cb();
}, trigger: 'blur' },
],
userType: [
{ required: true, message: '请选择用户类型', trigger: 'blur' },
],
status: [
{ required: true, message: '请选择用户状态', trigger: 'blur' },
],
},
}
}
}
</script>
<template>
<div class="page">
<LayoutTable :data='tableData' :config='tableConfig' notAdd notDel/>
</div>
</template>
<script>
import table from '@/assets/mixins/table';
export default {
mixins: [table],
methods: {
},
data() {
return {
config: {
columns: [
{
type: 'selection',
width: 60,
},
{
prop: 'id',
label: 'ID',
width: 60,
},
{
prop: 'code',
label: '验证码',
},
{
prop: 'url',
label: '校验地址',
},
{
prop: 'mobile',
label: '手机号码',
},
{
prop: 'email',
label: '校验邮箱',
},
{
prop: 'type',
label: '校验方式',
width: 130,
formatter: this.formatter,
},
{
prop: 'sessionId',
label: '会话ID'
},
{
prop: 'ip',
label: 'IP地址'
},
{
prop: 'createTime',
label: '创建时间'
},
{
prop: 'lapseTime',
label: '失效时间'
},
{
label: '操作',
formatter: (row)=> {
return (
<table-buttons row={row} onEdit={this.toEdit} onDel={this.toDel} />
)
},
},
],
search: [
{
name: 'mobile',
type: 'text',
label: '手机号码',
},
]
},
}
}
}
</script>
// 用户管理
<template>
<layout-form>
<el-form
:model="form"
:loading="loading"
:rules="rules"
size='small'
label-width='100px'
ref="form"
>
<el-row>
<Field label="登录名称" prop="loginName" v-model="form.loginName"/>
<Field label="登录密码" prop="loginPwd" v-model="form.loginPwd" v-if='pageInfo.type === "add"' />
<Field label="用户昵称" prop="realName" v-model="form.realName" />
<Field label="手机号码" prop="mobile" v-model="form.mobile" />
<Field label="用户类型" prop="userType" v-model="form.userType" :enumData='dict.userType' type='select' />
<Field label="用户状态" prop="status" v-model="form.status" :enumData='dict.status' type='select' />
</el-row>
<form-buttons @submit='submitForm'/>
</el-form>
</layout-form>
</template>
<script>
import form from '@/assets/mixins/form';
export default {
mixins: [form],
data() {
return {
toString: ['status', 'userType'],
rules: {
loginName: [
{ required: true, message: '请输入登录名称', trigger: 'blur' },
],
loginPwd: [
{ required: true, message: '请输入登录密码', trigger: 'blur' },
],
realName: [
{ required: true, message: '请输入用户昵称', trigger: 'blur' },
],
mobile: [
{ required: true, message: '请输入手机号码', trigger: 'blur' },
{ required: true, validator: (rule, val, cb)=>{
if(!/^1[0-9]{10}$/.test(val)){
return cb(new Error('手机号码格式不正确'))
}
cb();
}, trigger: 'blur' },
],
userType: [
{ required: true, message: '请选择用户类型', trigger: 'blur' },
],
status: [
{ required: true, message: '请选择用户状态', trigger: 'blur' },
],
},
}
}
}
</script>
package com.mortals.xhx.base.framework;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import org.springframework.util.ObjectUtils;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* @author: zxfei
* @date: 2022/6/30 10:49
* @description:
**/
public class CustomJsonDateDeserializer extends JsonDeserializer<Date> {
@Override
public Date deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String date = jp.getText();
if (!ObjectUtils.isEmpty(date)) {
try {
return format.parse(date);
} catch (ParseException e) {
return null;
}
} else {
return null;
}
}
}
package com.mortals.xhx.base.framework;
import org.springframework.http.MediaType;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import java.util.ArrayList;
import java.util.List;
/**
* @author: zxfei
* @date: 2022/6/28 15:57
* @description:
**/
// 创建一个新的转换器 解析微信的 [text/plain]
public class WxMessageConverter extends MappingJackson2HttpMessageConverter {
public WxMessageConverter() {
List<MediaType> mediaTypes = new ArrayList<>();
mediaTypes.add(MediaType.TEXT_PLAIN);
setSupportedMediaTypes(mediaTypes);
}
}
\ No newline at end of file
package com.mortals.xhx.base.framework.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ApiUserAuth {
String msg() default "";
String params() default "";
}
package com.mortals.xhx.base.framework.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* @author: zxfei
* @date: 2022/2/15 13:16
* @description:
**/
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Bean
public CorsFilter corsFilter(){
//初始化配置对象
CorsConfiguration configuration = new CorsConfiguration();
//允许跨域访问的域名
configuration.addAllowedOrigin("*");
// configuration.setAllowCredentials(true); //运行携带cookie
configuration.addAllowedMethod("*"); //代表所有请求方法
configuration.addAllowedHeader("*"); //允许携带任何头信息
//初始化cors配置源对象
UrlBasedCorsConfigurationSource configurationSource=new UrlBasedCorsConfigurationSource();
configurationSource.registerCorsConfiguration("/**",configuration);
//返回CorSfilter实例,参数
return new CorsFilter(configurationSource);
}
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowCredentials(true)
.allowedOrigins("*")
.allowedMethods(new String[] { "GET", "POST","PUT","DELETE"})
.allowedHeaders("*")
.exposedHeaders("*");
}
}
package com.mortals.xhx.base.framework.config;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @author: zxfei
* @date: 2022/6/6 15:05
* @description:添加跨域响应
**/
@Component
public class CrossInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "*");
response.setHeader("Access-Control-Allow-Credentials", "true");
return true;
}
}
package com.mortals.xhx.base.framework.config;
import com.mortals.framework.filter.RepeatableFilter;
import com.mortals.framework.filter.XssFilter;
import com.mortals.framework.util.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import javax.servlet.DispatcherType;
import java.util.HashMap;
import java.util.Map;
/**
* Filter配置
*
* @author zxfei
*/
//@Configuration
public class FilterConfig {
@Value("${xss.enabled}")
private String enabled;
@Value("${xss.excludes}")
private String excludes;
@Value("${xss.urlPatterns}")
private String urlPatterns;
@SuppressWarnings({"rawtypes", "unchecked"})
@Bean
public FilterRegistrationBean xssFilterRegistration() {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setDispatcherTypes(DispatcherType.REQUEST);
registration.setFilter(new XssFilter());
registration.addUrlPatterns(StringUtils.split(urlPatterns, ","));
registration.setName("xssFilter");
registration.setOrder(FilterRegistrationBean.HIGHEST_PRECEDENCE);
Map<String, String> initParameters = new HashMap<String, String>();
initParameters.put("excludes", excludes);
initParameters.put("enabled", enabled);
registration.setInitParameters(initParameters);
return registration;
}
@SuppressWarnings({"rawtypes", "unchecked"})
@Bean
public FilterRegistrationBean someFilterRegistration() {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(new RepeatableFilter());
registration.addUrlPatterns("/*");
registration.setName("repeatableFilter");
registration.setOrder(FilterRegistrationBean.LOWEST_PRECEDENCE);
return registration;
}
}
package com.mortals.xhx.base.framework.config;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.client.codec.Codec;
import org.redisson.codec.JsonJacksonCodec;
import org.redisson.config.Config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* RedissonConfig配置
*
* @author: zxfei
* @date: 2022/8/8 16:02
*/
//@Configuration
//@ConfigurationProperties(prefix = "spring.redis")
@Slf4j
@Data
public class RedissonConfig {
private String host;
private int port;
private String password;
private int database;
//@Bean
public RedissonClient redissonClient() {
RedissonClient redissonClient;
Config config = new Config();
String url = "redis://" + host + ":" + port;
// 单节点配置
config.useSingleServer().setAddress(url).setDatabase(database).setPassword(password);
//使用json序列化方式
Codec codec = new JsonJacksonCodec();
config.setCodec(codec);
// 主从配置
/*config.useMasterSlaveServers()
// 设置redis主节点
.setMasterAddress("redis://192.168.1.120:6379")
// 设置redis从节点
.addSlaveAddress("redis://192.168.1.130:6379", "redis://192.168.1.140:6379");*/
// 哨兵部署方式,sentinel是采用Paxos拜占庭协议,一般sentinel至少3个节点
/*config.useSentinelServers()
.setMasterName("my-sentinel-name")
.addSentinelAddress("redis://192.168.1.120:6379")
.addSentinelAddress("redis://192.168.1.130:6379")
.addSentinelAddress("redis://192.168.1.140:6379");*/
// 集群部署方式,cluster方式至少6个节点,3主3从,3主做sharding,3从用来保证主宕机后可以高可用
/*config.useClusterServers()
// 集群状态扫描间隔时间,单位是毫秒
.setScanInterval(2000)
.addNodeAddress("redis://192.168.1.120:6379")
.addNodeAddress("redis://192.168.1.130:6379")
.addNodeAddress("redis://192.168.1.140:6379")
.addNodeAddress("redis://192.168.1.150:6379")
.addNodeAddress("redis://192.168.1.160:6379")
.addNodeAddress("redis://192.168.1.170:6379");*/
// 云托管部署方式,这种方式主要解决redis提供商为云服务的提供商的redis连接,比如亚马逊云、微软云
/*config.useReplicatedServers()
// 主节点变化扫描间隔时间
.setScanInterval(2000)
.addNodeAddress("redis://192.168.1.120:6379")
.addNodeAddress("redis://192.168.1.130:6379")
.addNodeAddress("redis://192.168.1.140:6379");*/
redissonClient = Redisson.create(config);
return redissonClient;
}
}
\ No newline at end of file
package com.mortals.xhx.base.framework.filter;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.util.ContentCachingRequestWrapper;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
*
* 请求过滤链
* @author: zxfei
* @date: 2022/4/20 14:52
*/
//@Component
@Slf4j
public class RequestFilter extends OncePerRequestFilter implements Filter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
try {
request = new ContentCachingRequestWrapper(request);
filterChain.doFilter(request, response);
} catch (Exception e) {
throw e;
} finally {
//清理ThreadLocal
MDC.clear();
}
}
/*private void setUsername(HttpServletRequest request) {
//通过token解析出username
String token = authTokenService.getToken(request);
//String token = request.getHeader("token");
if (!ObjectUtils.isEmpty(token)) {
MDC.put("token",token);
MDC.put("token", token);
try {
SessionUserInfo info = tokenService.getUserInfo();
if (info != null) {
String username = info.getUsername();
MDC.put("username", username);
}
} catch (CommonJsonException e) {
log.info("无效的token:{}", token);
}
}
}*/
}
package com.mortals.xhx.base.framework.interceptor;
import com.alibaba.fastjson.JSONObject;
import com.mortals.framework.ap.SysConstains;
import com.mortals.framework.service.IAuthTokenService;
import com.mortals.framework.service.ICacheService;
import com.mortals.framework.service.IUser;
import com.mortals.framework.util.DateUtils;
import com.mortals.framework.util.StringUtils;
import com.mortals.xhx.base.system.user.model.UserEntity;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletRequest;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
/**
* token验证处理
*
* @author zxfei
*/
@Service
@Order(1)
@Slf4j
public class AuthTokenServiceImpl implements IAuthTokenService {
// 令牌自定义标识
@Value("${token.header:Authorization}")
private String header;
// 令牌秘钥
@Value("${token.secret:026db82420614469897fcc2dc1b4ce38}")
private String secret;
// 令牌有效期(默认60分钟)
@Value("${token.expireTime:60}")
private int expireTime;
// 令牌前缀
@Value("${token.prefix:}")
private String tokenPrefix;
// redis db
@Value("${spring.redis.database:}")
private Integer db;
@Value("${token.database:0}")
private Integer portalDb;
@Value("${platform.type:cloud}")
private String platFormType;//版本,默认云服务版本
protected static final Long SECOND = 1l;
protected static final Long SECOND_MINUTE = 60 * SECOND;
protected static final Long SECOND_HOUR = 60 * SECOND_MINUTE;
protected static final Long SECOND_DAY = 24 * SECOND_HOUR;
protected static final Long SECOND_WEEK = 7 * SECOND_DAY;
private static final Long SECOND_MINUTE_TEN = 1 * SECOND_MINUTE;
@Autowired
private ICacheService cacheService;
/**
* 获取信息
*
* @return 用户信息
*/
@Override
public IUser getLoginUser(HttpServletRequest request) {
// 获取请求携带的令牌
String token = getToken(request);
if (StringUtils.isNotEmpty(token)) {
try {
Claims claims = parseToken(token);
String uuid = (String) claims.get(SysConstains.LOGIN_USER_KEY);
String userKey = getTokenKey(uuid);
// Rest<String> rest = userFeign.getToken(userKey);
// String userStr = rest.getData();
String userStr = "";
userStr = cacheService.get(userKey);
if (StringUtils.isNotEmpty(userStr)) {
UserEntity userEntity = JSONObject.parseObject(userStr, UserEntity.class);
userEntity.setToken(token);
return userEntity;
}
} catch (Exception e) {
log.error("解析jwt token异常!", e);
return null;
}
}
return null;
}
/**
* 设置用户信息
*/
@Override
public void setUser(IUser user) {
if (StringUtils.isNotNull(user) && StringUtils.isNotEmpty(user.getToken())) {
refreshToken(user);
}
}
/**
* 删除用户身份信息
*/
@Override
public void delUser(String token) {
if (StringUtils.isNotEmpty(token)) {
String userKey = getTokenKey(token);
cacheService.del(userKey);
}
}
/**
* 创建令牌
*
* @param user 用户信息
* @return 令牌
*/
@Override
public String createToken(IUser user) {
// String token = IdUtil.fastSimpleUUID();
// user.setToken(token);
refreshToken(user);
Map<String, Object> claims = new HashMap<>();
claims.put(SysConstains.LOGIN_USER_KEY, user.getToken());
return createToken(claims);
}
/**
* 验证令牌有效期,相差不足20分钟,自动刷新缓存
*
* @param user
* @return 令牌
*/
@Override
public void verifyToken(IUser user) {
long expireTime = user.getExpireTime();
long currentTime = System.currentTimeMillis();
if (expireTime - currentTime <= SECOND_MINUTE_TEN) {
log.info("不足十分钟,刷新过期时间");
refreshToken(user);
}
}
/**
* 刷新令牌有效期
*
* @param user 信息
*/
public void refreshToken(IUser user) {
//user.setLoginTime(System.currentTimeMillis());
user.setExpireTime(user.getLoginTime() == null ? System.currentTimeMillis() : user.getLoginTime() + expireTime * SECOND_MINUTE);
// 根据uuid将user缓存
String userKey = getTokenKey(user.getToken());
//设置有效时间 单位秒
cacheService.set(userKey, user, expireTime * SECOND_MINUTE);
}
/**
* 从数据声明生成令牌
*
* @param claims 数据声明
* @return 令牌
*/
private String createToken(Map<String, Object> claims) {
String token = Jwts.builder()
.setExpiration(DateUtils.addCurrDate(7))
.setClaims(claims)
.signWith(SignatureAlgorithm.HS256, Base64.getEncoder()
.encodeToString(secret.getBytes())).compact();
return token;
}
/**
* 从令牌中获取数据声明
*
* @param token 令牌
* @return 数据声明
*/
@Override
public Claims parseToken(String token) {
return Jwts.parser()
.setSigningKey(Base64.getEncoder().encodeToString(secret.getBytes()))
.parseClaimsJws(token)
.getBody();
}
/**
* 从令牌中获取用户
*
* @param token 令牌
* @return 用户名
*/
@Override
public String getUserNumFromToken(String token) {
Claims claims = parseToken(token);
return claims.getSubject();
}
/**
* 获取请求token
*
* @param request
* @return token
*/
@Override
public String getToken(HttpServletRequest request) {
String token = request.getHeader(header);
if (StringUtils.isNotEmpty(token) && token.startsWith(tokenPrefix)) {
token = token.replace(tokenPrefix, "");
}
return token;
}
private String getTokenKey(String uuid) {
return SysConstains.LOGIN_TOKEN_KEY + uuid;
}
}
package com.mortals.xhx.base.framework.interceptor;
import com.alibaba.fastjson.JSONObject;
import com.mortals.framework.annotation.UnAuth;
import com.mortals.framework.common.Rest;
import com.mortals.framework.service.IAuthTokenService;
import com.mortals.framework.service.IUser;
import com.mortals.framework.util.AESUtil;
import com.mortals.framework.utils.ServletUtils;
import com.mortals.framework.web.interceptor.BaseInterceptor;
import com.mortals.xhx.base.framework.config.InterceptorConfig;
import com.mortals.xhx.common.code.ApiRespCodeEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.resource.ResourceHttpRequestHandler;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import static com.mortals.xhx.common.key.ErrorCode.*;
import static com.mortals.xhx.common.key.ErrorCode.ERROR_USER_OPERATION_CONTENT;
/**
* 用户权限验证,基于token
*
* @author: zxfei
* @date: 2022/4/24 11:04
*/
@Component
public class AuthUserInterceptor extends BaseInterceptor {
@Autowired
private InterceptorConfig config;
@Autowired
private IAuthTokenService authTokenService;
@Override
public int getOrder() {
return Integer.MAX_VALUE - 9;
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
JSONObject ret = new JSONObject();
if(handler instanceof HandlerMethod){
HandlerMethod handlerMethod = (HandlerMethod) handler;
Method method = handlerMethod.getMethod();
UnAuth annotation = method.getAnnotation(UnAuth.class);
if (annotation != null) {
//取消校验
return true;
}
}else if(handler instanceof ResourceHttpRequestHandler){
return true;
}
try {
String uri = request.getServletPath();
//校验配置的请求路径是否需要检查权限
if (config.needCheckAuth(uri)) {
//需要校验权限
boolean auth = this.checkAuth(request, uri, config.getSecurityKey());
if (!auth) {
//校验token不正常
String token = authTokenService.getToken(request);
if(ObjectUtils.isEmpty(token)){
ServletUtils.renderString(response, JSONObject.toJSONString(Rest.fail(ERROR_TOKEN_UNAUTHORIZED, ERROR_TOKEN_UNAUTHORIZED_CONTENT)));
return false;
}
//不存在时候 如果是管理员也不做拦截
IUser loginUser = authTokenService.getLoginUser(request);
if (ObjectUtils.isEmpty(loginUser)) {
ServletUtils.renderString(response, JSONObject.toJSONString(Rest.fail(ERROR_TOKEN_EXPIRED, ERROR_TOKEN_EXPIRED_CONTENT)));
return false;
} else if (loginUser.isAdmin() || loginUser.getUserType() == 1) {
return super.preHandle(request, response, handler);
} else {
ServletUtils.renderString(response, JSONObject.toJSONString(Rest.fail(ERROR_USER_OPERATION, ERROR_USER_OPERATION_CONTENT)));
return false;
}
}
}
} catch (Exception e) {
logger.error("权限校验拦截请求处理异常-->" + e.getMessage());
writeJsonResponse(response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "用户权限校验异常");
return false;
}
return super.preHandle(request, response, handler);
}
private boolean checkAuth(HttpServletRequest request, String requestUrl, String securityKey) throws Exception {
int code = requestUrl.hashCode() & (Integer.MAX_VALUE - 1);
IUser loginUser = authTokenService.getLoginUser(request);
if (ObjectUtils.isEmpty(loginUser)) return false;
String menuUrl = loginUser.getMenuUrl();
if (ObjectUtils.isEmpty(menuUrl)) return false;
menuUrl = AESUtil.decrypt(menuUrl, securityKey);
String codes = "," + menuUrl + ",";
String codeKey = "," + code + ",";
if (codes.indexOf(codeKey) != -1) {
return true;
}
return false;
}
}
package com.mortals.xhx.base.login.web;
import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSONObject;
import com.mortals.framework.ap.CookieService;
import com.mortals.framework.ap.GlobalSysInfo;
import com.mortals.framework.ap.SysConstains;
import com.mortals.framework.common.Rest;
import com.mortals.framework.service.IAuthTokenService;
import com.mortals.framework.service.ICacheService;
import com.mortals.framework.service.IUser;
import com.mortals.framework.util.AESUtil;
import com.mortals.framework.util.DateUtils;
import com.mortals.framework.util.HttpUtil;
import com.mortals.framework.util.StringUtils;
import com.mortals.framework.web.BaseCRUDJsonBodyMappingController;
import com.mortals.xhx.base.system.menu.model.MenuEntity;
import com.mortals.xhx.base.system.menu.service.MenuService;
import com.mortals.xhx.base.system.resource.service.ResourceService;
import com.mortals.xhx.base.system.user.model.UserEntity;
import com.mortals.xhx.base.system.user.service.UserService;
import com.mortals.xhx.base.system.valid.service.ValidCodeService;
import com.mortals.xhx.common.key.RedisKey;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Set;
import static com.mortals.xhx.common.key.ErrorCode.ERROR_TOKEN_EXPIRED;
import static com.mortals.xhx.common.key.ErrorCode.ERROR_TOKEN_EXPIRED_CONTENT;
@RestController
@Slf4j
@RequestMapping("login")
public class LoginController extends BaseCRUDJsonBodyMappingController<UserService, UserEntity, Long> implements InitializingBean {
@Autowired
private UserService userService;
@Autowired
private ValidCodeService validCodeService;
@Autowired
private ResourceService resourceService;
@Autowired
private MenuService menuService;
@Autowired
private ICacheService cacheService;
@Autowired
private IAuthTokenService authTokenService;
@RequestMapping("login")
public String login(@RequestBody LoginForm loginForm) throws Exception {
JSONObject ret = new JSONObject();
String loginName = loginForm.getLoginName();
String password = loginForm.getPassword();
String ip = super.getRequestIP(request);
if (StringUtils.isEmpty(loginName) || StringUtils.isEmpty(password)) {
ret.put(KEY_RESULT_CODE, VALUE_RESULT_FAILURE);
ret.put(KEY_RESULT_MSG, "未获取到用户信息,请重新登录");
return ret.toJSONString();
}
UserEntity userEntity = null;
try {
loginForm.validate();
userEntity = userService.doLogin(loginName, password, ip);
userEntity.setLastLoginAddress(ip);
recordSysLog(request, userEntity, "用户登录系统成功!");
// 返回拥有的菜单数据
Set<String> urls = resourceService.findUrlSetByUserId(userEntity.getId());
List<MenuEntity> outlookBarList = menuService.findTreeMenu(userEntity, urls);
String currUserName = userEntity.getRealName();
if (currUserName == null || currUserName.trim().length() == 0) {
currUserName = "管理员";
}
JSONObject data = new JSONObject();
data.put("currUserName", currUserName);
data.put("barList", outlookBarList);
data.put("id", userEntity.getId());
data.put("userType", userEntity.getUserType());
userEntity.setLoginTime(System.currentTimeMillis());
userEntity.setToken(IdUtil.fastSimpleUUID());
userEntity.setExpireTime(DateUtils.addCurrDate(7).getTime());
userEntity.setMenuUrl(generateMenuUrlCode(urls));
String token = authTokenService.createToken(userEntity);
data.put("token", token);
//设置token 和过期时间
//data.put("expiresTime", DateUtils.addCurrDate(7).getTime());
generateMenuUrlCode(urls);
//this.generateBlackCookie(request, response, loginName, urls);
ret.put(KEY_RESULT_DATA, data);
ret.put(KEY_RESULT_CODE, VALUE_RESULT_SUCCESS);
ret.put(KEY_RESULT_MSG, "用户登录系统成功!");
ret.put("resources", urls);
return ret.toJSONString();
} catch (Exception e) {
log.error("login error ", e);
if (userEntity == null) {
userEntity = new UserEntity();
userEntity.setLoginName(loginName);
}
ret.put(KEY_RESULT_CODE, VALUE_RESULT_FAILURE);
ret.put(KEY_RESULT_MSG, super.convertException(e));
return ret.toJSONString();
}
}
@RequestMapping("logout")
public void logout(HttpServletRequest request, HttpServletResponse response) throws Exception {
recordSysLog(request, "退出登录");
super.removeCurrUser(request);
this.deleteBlackCookie(request, response);
}
@RequestMapping("index")
public String index() throws Exception {
JSONObject ret = new JSONObject();
IUser user = this.getCurUser();
if (user == null) {
return JSONObject.toJSONString(Rest.fail(ERROR_TOKEN_EXPIRED, ERROR_TOKEN_EXPIRED_CONTENT));
}
Set<String> urls = resourceService.findUrlSetByUserId(user.getId());
List<MenuEntity> outlookBarList = menuService.findTreeMenu(user, urls);
String currUserName = user.getRealName();
if (currUserName == null || currUserName.trim().length() == 0) {
currUserName = "管理员";
}
JSONObject data = new JSONObject();
String token = authTokenService.getToken(request);
data.put("token", token);
data.put("currUserName", currUserName);
data.put("barList", outlookBarList);
data.put("id", user.getId());
data.put("userType", user.getUserType());
ret.put(KEY_RESULT_DATA, data);
//this.generateBlackCookie(request, response, user.getLoginName(), urls);
ret.put(KEY_RESULT_CODE, VALUE_RESULT_SUCCESS);
ret.put(KEY_RESULT_MSG, "用户登录系统成功!");
ret.put("resources", urls);
return ret.toJSONString();
}
private void generateBlackCookie(HttpServletRequest request, HttpServletResponse response, String loginName, Set<String> urls) {
try {
String cacheKey = RedisKey.KEY_MENU_CACHE + loginName;
String securityKey = GlobalSysInfo.getPropertyValue(SysConstains.PROP_COOKIE_SECURITY_KEY);
//应为Cookie会超长,所以改为仅存储key将值放入redis
//CookieService.setCookieForAuth(request, response, securityKey, null);
StringBuilder sb = new StringBuilder();
if (urls != null && urls.size() > 0) {
for (String url : urls) {
int index = url.hashCode() & (Integer.MAX_VALUE - 1);
sb.append(index).append(",");
}
}
String menuUrl = sb.toString();
menuUrl = AESUtil.encrypt(menuUrl, securityKey);
cacheService.set(cacheKey, menuUrl, 604800);
HttpUtil.setCookieValue(request, response, SysConstains.COOKIE_MENU, cacheKey, -1);
} catch (Throwable e) {
}
}
private String generateMenuUrlCode(Set<String> urls) {
try {
String securityKey = GlobalSysInfo.getPropertyValue(SysConstains.PROP_COOKIE_SECURITY_KEY);
StringBuilder sb = new StringBuilder();
if (urls != null && urls.size() > 0) {
for (String url : urls) {
int index = url.hashCode() & (Integer.MAX_VALUE - 1);
sb.append(index).append(",");
}
}
String menuUrl = sb.toString();
return AESUtil.encrypt(menuUrl, securityKey);
} catch (Throwable e) {
log.error("编码异常", e);
return null;
}
}
@RequestMapping("validcode")
public String validCode(HttpServletRequest request, HttpServletResponse response, LoginForm loginForm) {
JSONObject ret = new JSONObject();
String loginName = loginForm.getLoginName();
String password = loginForm.getPassword();
if (StringUtils.isEmpty(loginName) || StringUtils.isEmpty(password)) {
ret.put(KEY_RESULT_CODE, VALUE_RESULT_FAILURE);
ret.put(KEY_RESULT_MSG, "登录名或密码为空");
}
UserEntity user = null;
try {
user = userService.doCheckUser(loginName, password);
if (user == null) {
ret.put(KEY_RESULT_CODE, VALUE_RESULT_FAILURE);
ret.put(KEY_RESULT_MSG, "用户名或密码不正确");
} else if (StringUtils.isEmpty(user.getMobile())) {
ret.put(KEY_RESULT_CODE, VALUE_RESULT_FAILURE);
ret.put(KEY_RESULT_MSG, "用户无正确的手机号");
} else {
String mobile = StringUtils.trim(user.getMobile());
String sessionId = request.getSession().getId();
String ip = super.getRequestIP(request);
boolean result = validCodeService.createSmsValidCode(sessionId, ip, mobile);
if (result) {
ret.put(KEY_RESULT_CODE, VALUE_RESULT_SUCCESS);
} else {
ret.put(KEY_RESULT_CODE, VALUE_RESULT_FAILURE);
ret.put(KEY_RESULT_MSG, "验证码发送失败,请稍后在试!");
}
}
} catch (Exception e) {
ret.put(KEY_RESULT_CODE, VALUE_RESULT_FAILURE);
ret.put(KEY_RESULT_MSG, "验证码发送失败:" + super.convertException(e));
} finally {
if (user == null) {
user = new UserEntity();
user.setLoginName(loginName);
}
recordSysLog(request, user, "用户获取短信验证码");
}
return ret.toJSONString();
}
protected void deleteBlackCookie(HttpServletRequest request, HttpServletResponse response) {
try {
CookieService.deleteCookieForAuth(request, response);
} catch (Throwable e) {
}
}
@RequestMapping("parseToken")
public IUser parseToken() throws Exception {
IUser userEntity = authTokenService.getLoginUser(request);
if (!ObjectUtils.isEmpty(userEntity)) {
authTokenService.verifyToken(userEntity);
return userEntity;
}
return null;
}
@Override
public void afterPropertiesSet() throws Exception {
log.info("初始化加载单机版登录。。。");
}
}
package com.mortals.xhx.base.system.user.model.vo;
import com.mortals.framework.model.BaseEntityLong;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
/**
* 用户信息业务视图对象
*
* @author zxfei
* @date 2022-07-05
*/
@Data
public class UserVo extends BaseEntityLong {
/**
* 站点名称
*/
private String siteName;
private String roleIds;
/**
* 唯一标识
*/
private String token;
/**
* 菜单栏
*/
private String menuUrl;
/**
* 登录时间
*/
private Long loginTime;
/**
* 过期时间
*/
private Long expireTime;
private Long siteId;
private Long customerId;
}
\ No newline at end of file
package com.mortals.xhx.common.key;
/**
* 错误码
*
* @author: zxfei
* @date: 2022/5/12 14:56
*/
public interface ErrorCode {
public static final int STATUS_MS_EXCEPTION = 500;
public static final int STATUS_VALIDATE_EXCEPTION = 420;
public static final int STATUS_UNCHECKED_EXCEPTION = 605;
public static final int STATUS_TOKEN_NULL_EXCEPTION = 604;
public static final int STATUS_CODE_SUCCESS = 0;
public static final int STATUS_CODE_WARN = 1;
public static final int STATUS_CODE_ERROR = 2;
public static final int STATUS_CODE_INFO = 3;
public static final int STATUS_CODE_TOKEN_EXPIRED = 4;
public static final int STATUS_CODE_FATAL = 5;
public static final int STATUS_CODE_TRADE_PWD_NOT_SET = 6;
public static final int STATUS_ACCOUNT_LOCKED = 7;
public static final int STATUS_TRADE_PWD_OVER_THREE_TIME = 8;
public static final int STATUS_TRADE_PWD_ERROR = 9;
public static final int STATUS_EMPTY_PWD_ERROR = 10;
public static final int STATUS_TEL_NOT_RGI_ERROR = 11;
public static final int STATUS_TEL_ALREADY_REGI = 12;
public static final int STATUS_SAFETY_RISK = 13;
public static final int STATUS_LOGIN_CODE = 15;
public static final int BOOK_FAKUAN_CODE = 16;
public static final String ERROR_TRADE_PWD_OVER_THREE_TIME = "支付密码错误,请15分钟后再试";
public static final String ERROR_TRADE_PWD_ERROR = "支付密码错误,请重试";
public static final String ERROR_EMPTY_PWD_ERROR = "请设置登录密码";
public static final String ERROR_TEL_NOT_RGI = "该号码未注册";
public static final String ERROR_USERNAME_OR_PASSWORD = "用户名或者密码错误";
public static final String ERROR_TRADE_PWD = "交易密码错误";
public static final String ERROR_FORBIDDEN_OPER = "非法操作";
public static final String ERROR_TRADE_PWD_NOT_SET = "非法操作";
public static final String ERROR_NOT_REAL_NAME_AUTH = "您未实名认证,禁止该操作";
public static final String ERROR_INTERNAL_SERVER_ERROR = "服务器内部错误";
public static final String ERROR_UNAUTHORIZED = "token不正确或已过期";
public static final String ERROR_TOKEN_IS_NULL = "token不能为空";
public static final String ERROR_MISS_SERVLET = "服务不存在";
public static final String ERROR_CAPTCHA_OFTEN = "验证码已发送";
public static final String ERROR_CAPTCHA_WRONG = "验证码错误";
public static final String ERROR_TEL_ALREADY_REGI = "该手机号已被注册";
public static final String ERROR_CODE_DUPLICATE_KEY = "重复添加信息(含部分)";
public static final String ERROR_NOT_EXITS = "对应记录不存在";
public static final String ERROR_STATUS_CATEGORY = "状态错误";
public static final String ERROR_FRIEND_SHIP_ALREADY = "已经是你好友";
public static final String ERROR_FRIEND_SHIP_WAIT = "已向改好友发出邀请,等待接受";
public static final String ERROR_CODE_ACCOUNT_LOCKED = "账号被锁定,请联系客服";
public static final String WARN_ARGUMENT = "参数错误";
public static final String ERROR_USERNAME_EXIST = "该号码已被注册";
public static final String ERROR_SAFETY_RISK = "不在常用设备上登录";
public static final String INFO_TEL_BIND = "手机号码已经被绑定";
public static final String INFO_TEL_FORMAT_WRONG = "手机号码格式不正确";
public static final String ERROR_NOT_FOUND = "404 not found";
public static final String DISABLED="该账号已被封禁,如有疑问请联系平台";
public static final String DATENULL="缺少参数";
public static final String ERRDATE="无效参数";
public static final String ERRSTAE="状态异常";
public static final String EXTDATE="参数异常";
public static final String NUMEXE="账号异常";
public static final String CAPDON="资产已被冻结,如有疑问请联系平台";
public static final String CONOTS="操作失败";
public static final String OK="成功!";
public static final String TOKENX="身份验证失败,请重新登录";
public static final String CAPNOT="充值余额不足请充值";
public static final String SYSNOT="系统繁忙,请稍后再试...";
public static final String NOWER="没有权限";
public static final String PAGEDATA="分页参数不能为空";
public static final String CARADD_MEMBERS="该司机已有绑定车辆,不能绑定多个";
public static final int DEVICE_CODE_IS_EMPTY = 1001;
public static final String DEVICE_CODE_IS_EMPTY_CONTENT = "当前设备编码为空!";
public static final int DEVICE_CODE_IS_EXIST = 1002;
public static final String DEVICE_CODE_IS_EXIST_CONTENT = "当前设备编码已存在!";
public static final int PRODUCT_IS_EMPTY = 1003;
public static final String PRODUCT_IS_EMPTY_CONTENT = "所属产品编码不存在!";
public static final int DEVICE_UNACTIVE = 1004;
public static final String DEVICE_UNACTIVE_CONTENT = "当前设备未激活,请在后台配置后再激活!";
public static final int PLATFORM_IS_EMPTY = 1005;
public static final String PLATFORM_IS_EMPTY_CONTENT = "当前设备编码不存在!";
public static final int PLATFORM_UNEXIST = 1006;
public static final String PLATFORM_UNEXIST_CONTENT = "当前设备所属产品平台未配置,请在后台配置后再激活!";
public static final int SITEID_IS_EMPTY = 1007;
public static final String SITEID_IS_EMPTY_CONTENT = "站点ID为空!";
public static final int DEVICE_CONFIG_IS_EMPTY = 1008;
public static final String DEVICE_CONFIG_IS_EMPTY_CONTENT = "设备创建,请完善设备配置信息!";
public static final int DEVICE_NOT_EXIST = 1009;
public static final String DEVICE_NOT_EXIST_CONTENT = "当前设备不存在!";
public static final int TOKEN_AUTH_FAIL = 1010;
public static final String TOKEN_AUTH_FAIL_CONTENT = "token认证失败!";
public static final int DEVICE_VERSION_UNEXIST = 1011;
public static final String DEVICE_VERSION_UNEXIST_CONTENT = "未找到设备版本信息!";
public static final int ERROR_TOKEN_EXPIRED = 9001;
public static final String ERROR_TOKEN_EXPIRED_CONTENT = "用户登录过期,请重新登录!";
public static final int ERROR_TOKEN_UNAUTHORIZED = 9002;
public static final String ERROR_TOKEN_UNAUTHORIZED_CONTENT = "token不正确或已过期";
public static final int ERROR_USER_OPERATION = 9009;
public static final String ERROR_USER_OPERATION_CONTENT = "用户无该操作权限!";
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment