初始化

This commit is contained in:
asd
2019-11-08 11:13:02 +08:00
commit 29cf6cfe47
2999 changed files with 288025 additions and 0 deletions

43
src/App.vue Normal file
View File

@@ -0,0 +1,43 @@
<template>
<div id="app">
<transition name="fade" mode="out-in">
<router-view></router-view>
</transition>
</div>
</template>
<script>
export default {
name: 'app',
}
</script>
<style lang="scss">
body {
margin: 0px;
padding: 0px;
font-family: Microsoft YaHei, Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, SimSun, sans-serif;
font-size: 14px;
-webkit-font-smoothing: antialiased;
}
#app {
position: absolute;
top: 0px;
bottom: 0px;
width: 100%;
}
a{
color: #56a9ff;
}
.fade-enter-active,
.fade-leave-active {
transition: all .2s ease;
}
.fade-enter,
.fade-leave-active {
opacity: 0;
}
</style>

BIN
src/assets/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@@ -0,0 +1,370 @@
*{margin: 0;padding: 0;list-style: none;}
/*
KISSY CSS Reset
理念1. reset 的目的不是清除浏览器的默认样式,这仅是部分工作。清除和重置是紧密不可分的。
2. reset 的目的不是让默认样式在所有浏览器下一致,而是减少默认样式有可能带来的问题。
3. reset 期望提供一套普适通用的基础样式。但没有银弹,推荐根据具体需求,裁剪和修改后再使用。
特色1. 适应中文2. 基于最新主流浏览器。
维护:玉伯<lifesinger@gmail.com>, 正淳<ragecarrier@gmail.com>
*/
/** 清除内外边距 **/
body, h1, h2, h3, h4, h5, h6, hr, p, blockquote, /* structural elements 结构元素 */
dl, dt, dd, ul, ol, li, /* list elements 列表元素 */
pre, /* text formatting elements 文本格式元素 */
form, fieldset, legend, button, input, textarea, /* form elements 表单元素 */
th, td /* table elements 表格元素 */ {
margin: 0;
padding: 0;
}
/** 设置默认字体 **/
body,
button, input, select, textarea /* for ie */ {
font: 12px/1.5 tahoma, arial, \5b8b\4f53, sans-serif;
}
h1, h2, h3, h4, h5, h6 { font-size: 100%; }
address, cite, dfn, em, var { font-style: normal; } /* 将斜体扶正 */
code, kbd, pre, samp { font-family: courier new, courier, monospace; } /* 统一等宽字体 */
small { font-size: 12px; } /* 小于 12px 的中文很难阅读,让 small 正常化 */
/** 重置列表元素 **/
ul, ol { list-style: none; }
/** 重置文本格式元素 **/
a { text-decoration: none; }
a:hover { text-decoration: underline; }
/** 重置表单元素 **/
legend { color: #000; } /* for ie6 */
fieldset, img { border: 0; } /* img 搭车:让链接里的 img 无边框 */
button, input, select, textarea { font-size: 100%; } /* 使得表单元素在 ie 下能继承字体大小 */
/* 注optgroup 无法扶正 */
/** 重置表格元素 **/
table { border-collapse: collapse; border-spacing: 0; }
/* 清除浮动 */
.ks-clear:after, .clear:after {
content: '\20';
display: block;
height: 0;
clear: both;
}
.ks-clear, .clear {
*zoom: 1;
}
.main {
padding: 30px 100px;
width: 960px;
margin: 0 auto;
}
.main h1{font-size:36px; color:#333; text-align:left;margin-bottom:30px; border-bottom: 1px solid #eee;}
.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;
}
.icon_lists li{
float:left;
width: 100px;
height:180px;
text-align: center;
list-style: none !important;
}
.icon_lists .icon{
font-size: 42px;
line-height: 100px;
margin: 10px 0;
color:#333;
-webkit-transition: font-size 0.25s ease-out 0s;
-moz-transition: font-size 0.25s ease-out 0s;
transition: font-size 0.25s ease-out 0s;
}
.icon_lists .icon:hover{
font-size: 100px;
}
.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,
.markdown pre {
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 pre {
border-radius: 6px;
background: #f7f7f7;
padding: 20px;
}
.markdown pre code {
border: none;
background: #f7f7f7;
margin: 0;
}
.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;
font-style: italic;
}
.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;
}
pre{
background: #fff;
}

View File

@@ -0,0 +1,70 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>IconFont</title>
<link rel="stylesheet" href="demo.css">
<link rel="stylesheet" href="iconfont.css">
</head>
<body>
<div class="main markdown">
<h1>IconFont 图标</h1>
<ul class="icon_lists clear">
<li>
<i class="icon iconfont xu-imagevector"></i>
<div class="name">密码登录</div>
<div class="fontclass">.xu-imagevector</div>
</li>
<li>
<i class="icon iconfont xu-saomadenglu01"></i>
<div class="name">扫码登录-01</div>
<div class="fontclass">.xu-saomadenglu01</div>
</li>
<li>
<i class="icon iconfont xu-saomadenglu"></i>
<div class="name">扫码登录</div>
<div class="fontclass">.xu-saomadenglu</div>
</li>
<li>
<i class="icon iconfont xu-saomadenglu2"></i>
<div class="name">扫码登录</div>
<div class="fontclass">.xu-saomadenglu2</div>
</li>
<li>
<i class="icon iconfont xu-mimadenglu1"></i>
<div class="name">密码登录</div>
<div class="fontclass">.xu-mimadenglu1</div>
</li>
</ul>
<h2 id="font-class-">font-class引用</h2>
<hr>
<p>font-class是unicode使用方式的一种变种主要是解决unicode书写不直观语意不明确的问题。</p>
<p>与unicode使用方式相比具有如下特点</p>
<ul>
<li>兼容性良好支持ie8+,及所有现代浏览器。</li>
<li>相比于unicode语意明确书写更直观。可以很容易分辨这个icon是什么。</li>
<li>因为使用class来定义图标所以当要替换图标时只需要修改class里面的unicode引用。</li>
<li>不过因为本质上还是使用的字体,所以多色图标还是不支持的。</li>
</ul>
<p>使用步骤如下:</p>
<h3 id="-fontclass-">第一步引入项目下面生成的fontclass代码</h3>
<pre><code class="lang-js hljs javascript"><span class="hljs-comment">&lt;link rel="stylesheet" type="text/css" href="./iconfont.css"&gt;</span></code></pre>
<h3 id="-">第二步:挑选相应图标并获取类名,应用于页面:</h3>
<pre><code class="lang-css hljs">&lt;<span class="hljs-selector-tag">i</span> <span class="hljs-selector-tag">class</span>="<span class="hljs-selector-tag">iconfont</span> <span class="hljs-selector-tag">xu-xxx</span>"&gt;&lt;/<span class="hljs-selector-tag">i</span>&gt;</code></pre>
<blockquote>
<p>"iconfont"是你项目下的font-family。可以通过编辑项目查看默认是"iconfont"。</p>
</blockquote>
</div>
</body>
</html>

View File

@@ -0,0 +1,103 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>IconFont</title>
<link rel="stylesheet" href="demo.css">
<script src="iconfont.js"></script>
<style type="text/css">
.icon {
/* 通过设置 font-size 来改变图标大小 */
width: 1em; height: 1em;
/* 图标和文字相邻时,垂直对齐 */
vertical-align: -0.15em;
/* 通过设置 color 来改变 SVG 的颜色/fill */
fill: currentColor;
/* path 和 stroke 溢出 viewBox 部分在 IE 下会显示
normalize.css 中也包含这行 */
overflow: hidden;
}
</style>
</head>
<body>
<div class="main markdown">
<h1>IconFont 图标</h1>
<ul class="icon_lists clear">
<li>
<svg class="icon" aria-hidden="true">
<use xlink:href="#xu-imagevector"></use>
</svg>
<div class="name">密码登录</div>
<div class="fontclass">#xu-imagevector</div>
</li>
<li>
<svg class="icon" aria-hidden="true">
<use xlink:href="#xu-saomadenglu01"></use>
</svg>
<div class="name">扫码登录-01</div>
<div class="fontclass">#xu-saomadenglu01</div>
</li>
<li>
<svg class="icon" aria-hidden="true">
<use xlink:href="#xu-saomadenglu"></use>
</svg>
<div class="name">扫码登录</div>
<div class="fontclass">#xu-saomadenglu</div>
</li>
<li>
<svg class="icon" aria-hidden="true">
<use xlink:href="#xu-saomadenglu2"></use>
</svg>
<div class="name">扫码登录</div>
<div class="fontclass">#xu-saomadenglu2</div>
</li>
<li>
<svg class="icon" aria-hidden="true">
<use xlink:href="#xu-mimadenglu1"></use>
</svg>
<div class="name">密码登录</div>
<div class="fontclass">#xu-mimadenglu1</div>
</li>
</ul>
<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="lang-js hljs javascript"><span class="hljs-comment">&lt;script src="./iconfont.js"&gt;&lt;/script&gt;</span></code></pre>
<h3 id="-css-">第二步加入通用css代码引入一次就行</h3>
<pre><code class="lang-js hljs javascript">&lt;style type=<span class="hljs-string">"text/css"</span>&gt;
.icon {
width: <span class="hljs-number">1</span>em; height: <span class="hljs-number">1</span>em;
vertical-align: <span class="hljs-number">-0.15</span>em;
fill: currentColor;
overflow: hidden;
}
&lt;<span class="hljs-regexp">/style&gt;</span></code></pre>
<h3 id="-">第三步:挑选相应图标并获取类名,应用于页面:</h3>
<pre><code class="lang-js hljs javascript">&lt;svg <span class="hljs-class"><span class="hljs-keyword">class</span></span>=<span class="hljs-string">"icon"</span> aria-hidden=<span class="hljs-string">"true"</span>&gt;<span class="xml"><span class="hljs-tag">
&lt;<span class="hljs-name">use</span> <span class="hljs-attr">xlink:href</span>=<span class="hljs-string">"#xu-xxx"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">use</span>&gt;</span>
</span>&lt;<span class="hljs-regexp">/svg&gt;
</span></code></pre>
</div>
</body>
</html>

View File

@@ -0,0 +1,108 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>IconFont</title>
<link rel="stylesheet" href="demo.css">
<style type="text/css">
@font-face {font-family: "iconfont";
src: url('iconfont.eot'); /* IE9*/
src: url('iconfont.eot#iefix') format('embedded-opentype'), /* IE6-IE8 */
url('iconfont.woff') format('woff'), /* chrome, firefox */
url('iconfont.ttf') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/
url('iconfont.svg#iconfont') format('svg'); /* iOS 4.1- */
}
.iconfont {
font-family:"iconfont" !important;
font-size:16px;
font-style:normal;
-webkit-font-smoothing: antialiased;
-webkit-text-stroke-width: 0.2px;
-moz-osx-font-smoothing: grayscale;
}
</style>
</head>
<body>
<div class="main markdown">
<h1>IconFont 图标</h1>
<ul class="icon_lists clear">
<li>
<i class="icon iconfont">&#xe604;</i>
<div class="name">密码登录</div>
<div class="code">&amp;#xe604;</div>
</li>
<li>
<i class="icon iconfont">&#xe600;</i>
<div class="name">扫码登录-01</div>
<div class="code">&amp;#xe600;</div>
</li>
<li>
<i class="icon iconfont">&#xe67e;</i>
<div class="name">扫码登录</div>
<div class="code">&amp;#xe67e;</div>
</li>
<li>
<i class="icon iconfont">&#xe62d;</i>
<div class="name">扫码登录</div>
<div class="code">&amp;#xe62d;</div>
</li>
<li>
<i class="icon iconfont">&#xe62e;</i>
<div class="name">密码登录</div>
<div class="code">&amp;#xe62e;</div>
</li>
</ul>
<h2 id="unicode-">unicode引用</h2>
<hr>
<p>unicode是字体在网页端最原始的应用方式特点是</p>
<ul>
<li>兼容性最好支持ie6+,及所有现代浏览器。</li>
<li>支持按字体的方式去动态调整图标大小,颜色等等。</li>
<li>但是因为是字体,所以不支持多色。只能使用平台里单色的图标,就算项目里有多色图标也会自动去色。</li>
</ul>
<blockquote>
<p>注意新版iconfont支持多色图标这些多色图标在unicode模式下将不能使用如果有需求建议使用symbol的引用方式</p>
</blockquote>
<p>unicode使用步骤如下</p>
<h3 id="-font-face">第一步拷贝项目下面生成的font-face</h3>
<pre><code class="lang-js hljs javascript">@font-face {
font-family: <span class="hljs-string">'iconfont'</span>;
src: url(<span class="hljs-string">'iconfont.eot'</span>);
src: url(<span class="hljs-string">'iconfont.eot?#iefix'</span>) format(<span class="hljs-string">'embedded-opentype'</span>),
url(<span class="hljs-string">'iconfont.woff'</span>) format(<span class="hljs-string">'woff'</span>),
url(<span class="hljs-string">'iconfont.ttf'</span>) format(<span class="hljs-string">'truetype'</span>),
url(<span class="hljs-string">'iconfont.svg#iconfont'</span>) format(<span class="hljs-string">'svg'</span>);
}
</code></pre>
<h3 id="-iconfont-">第二步定义使用iconfont的样式</h3>
<pre><code class="lang-js hljs javascript">.iconfont{
font-family:<span class="hljs-string">"iconfont"</span> !important;
font-size:<span class="hljs-number">16</span>px;font-style:normal;
-webkit-font-smoothing: antialiased;
-webkit-text-stroke-width: <span class="hljs-number">0.2</span>px;
-moz-osx-font-smoothing: grayscale;
}
</code></pre>
<h3 id="-">第三步:挑选相应图标并获取字体编码,应用于页面</h3>
<pre><code class="lang-js hljs javascript">&lt;i <span class="hljs-class"><span class="hljs-keyword">class</span></span>=<span class="hljs-string">"iconfont"</span>&gt;&amp;#x33;<span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">i</span>&gt;</span></span></code></pre>
<blockquote>
<p>"iconfont"是你项目下的font-family。可以通过编辑项目查看默认是"iconfont"。</p>
</blockquote>
</div>
</body>
</html>

View File

@@ -0,0 +1,27 @@
@font-face {font-family: "iconfont";
src: url('iconfont.eot?t=1545982074961'); /* IE9*/
src: url('iconfont.eot?t=1545982074961#iefix') format('embedded-opentype'), /* IE6-IE8 */
url('data:application/x-font-woff;charset=utf-8;base64,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') format('woff'),
url('iconfont.ttf?t=1545982074961') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/
url('iconfont.svg?t=1545982074961#iconfont') format('svg'); /* iOS 4.1- */
}
.iconfont {
font-family:"iconfont" !important;
font-size:16px;
font-style:normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.xu-imagevector:before { content: "\e604"; }
.xu-saomadenglu01:before { content: "\e600"; }
.xu-saomadenglu:before { content: "\e67e"; }
.xu-saomadenglu2:before { content: "\e62d"; }
.xu-mimadenglu1:before { content: "\e62e"; }

Binary file not shown.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

BIN
src/assets/img404/sign.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
src/assets/lang.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

BIN
src/assets/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

23
src/btnPermission.js Normal file
View File

@@ -0,0 +1,23 @@
/**
* Created by WebStorm.
* User: nirongxu
* Date: 2018/12/15
* Description: 文件描述
*/
import Vue from 'vue'
Vue.directive('roleBtn',{
bind:function (el,binding) {
let roleArr = binding.value;
let userRole = JSON.parse(sessionStorage.getItem('info')).role
if (roleArr && roleArr.indexOf(userRole) !== -1) {
return false
} else {
el.parentNode.removeChild(el);
}
}
})
export default Vue

View File

@@ -0,0 +1,107 @@
<template>
<div>
<div :id="id" :style="{width: width, height: height}"></div>
</div>
</template>
<script>
import echarts from 'echarts'
import westeros from './theme/westeros'
export default {
name: 'lineEcharts',
props: {
id: {
type: String,
default: 'myChart'
},
width: {
type: String,
default: '100%'
},
height: {
type: String,
default: '100%'
}
},
data() {
return {
chart: null
}
},
mounted() {
this.initChart()
},
methods: {
initChart() {
this.chart = echarts.init(document.getElementById(this.id),'westeros')
this.chart.setOption({
title: {
text: '折线图堆叠'
},
tooltip: {
trigger: 'axis'
},
legend: {
data:['邮件营销','联盟广告','视频广告','直接访问','搜索引擎']
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
toolbox: {
feature: {
saveAsImage: {}
}
},
xAxis: {
type: 'category',
boundaryGap: false,
data: ['周一','周二','周三','周四','周五','周六','周日']
},
yAxis: {
type: 'value'
},
series: [
{
name:'邮件营销',
type:'line',
stack: '总量',
data:[8200, 6320, 5010, 4340, 3400, 2300, 1100]
},
{
name:'联盟广告',
type:'line',
stack: '总量',
data:[2200, 3820, 1910, 2340, 4900, 3300, 1100]
},
{
name:'视频广告',
type:'line',
stack: '总量',
data:[2500, 4302, 5010, 2540, 6900, 5300, 6410]
},
{
name:'直接访问',
type:'line',
stack: '总量',
data:[5320, 7332, 9301, 6334, 5390, 4330, 1320]
},
{
name:'搜索引擎',
type:'line',
stack: '总量',
data:[8820, 1932, 5901, 7304, 2900, 3300, 8200]
}
]
})
}
}
}
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,514 @@
import echarts from 'echarts'
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(['exports', 'echarts'], factory);
} else if (typeof exports === 'object' && typeof exports.nodeName !== 'string') {
// CommonJS
factory(exports, require('echarts'));
} else {
// Browser globals
factory({}, echarts);
}
}(this, function (exports, echarts) {
var log = function (msg) {
if (typeof console !== 'undefined') {
console && console.error && console.error(msg);
}
};
if (!echarts) {
log('ECharts is not Loaded');
return;
}
echarts.registerTheme('westeros', {
"color": [
"#409eff",
"#59c4e6",
"#edafda",
"#93b7e3",
"#a5e7f0",
"#cbb0e3"
],
"backgroundColor": "rgba(0,0,0,0)",
"textStyle": {},
"title": {
"textStyle": {
"color": "#409eff"
},
"subtextStyle": {
"color": "#93b7e3"
}
},
"line": {
"itemStyle": {
"normal": {
"borderWidth": "2"
}
},
"lineStyle": {
"normal": {
"width": "2"
}
},
"symbolSize": "6",
"symbol": "emptyCircle",
"smooth": true
},
"radar": {
"itemStyle": {
"normal": {
"borderWidth": "2"
}
},
"lineStyle": {
"normal": {
"width": "2"
}
},
"symbolSize": "6",
"symbol": "emptyCircle",
"smooth": true
},
"bar": {
"itemStyle": {
"normal": {
"barBorderWidth": 0,
"barBorderColor": "#ccc"
},
"emphasis": {
"barBorderWidth": 0,
"barBorderColor": "#ccc"
}
}
},
"pie": {
"itemStyle": {
"normal": {
"borderWidth": 0,
"borderColor": "#ccc"
},
"emphasis": {
"borderWidth": 0,
"borderColor": "#ccc"
}
}
},
"scatter": {
"itemStyle": {
"normal": {
"borderWidth": 0,
"borderColor": "#ccc"
},
"emphasis": {
"borderWidth": 0,
"borderColor": "#ccc"
}
}
},
"boxplot": {
"itemStyle": {
"normal": {
"borderWidth": 0,
"borderColor": "#ccc"
},
"emphasis": {
"borderWidth": 0,
"borderColor": "#ccc"
}
}
},
"parallel": {
"itemStyle": {
"normal": {
"borderWidth": 0,
"borderColor": "#ccc"
},
"emphasis": {
"borderWidth": 0,
"borderColor": "#ccc"
}
}
},
"sankey": {
"itemStyle": {
"normal": {
"borderWidth": 0,
"borderColor": "#ccc"
},
"emphasis": {
"borderWidth": 0,
"borderColor": "#ccc"
}
}
},
"funnel": {
"itemStyle": {
"normal": {
"borderWidth": 0,
"borderColor": "#ccc"
},
"emphasis": {
"borderWidth": 0,
"borderColor": "#ccc"
}
}
},
"gauge": {
"itemStyle": {
"normal": {
"borderWidth": 0,
"borderColor": "#ccc"
},
"emphasis": {
"borderWidth": 0,
"borderColor": "#ccc"
}
}
},
"candlestick": {
"itemStyle": {
"normal": {
"color": "#edafda",
"color0": "transparent",
"borderColor": "#d680bc",
"borderColor0": "#8fd3e8",
"borderWidth": "2"
}
}
},
"graph": {
"itemStyle": {
"normal": {
"borderWidth": 0,
"borderColor": "#ccc"
}
},
"lineStyle": {
"normal": {
"width": 1,
"color": "#aaa"
}
},
"symbolSize": "6",
"symbol": "emptyCircle",
"smooth": true,
"color": [
"#409eff",
"#59c4e6",
"#edafda",
"#93b7e3",
"#a5e7f0",
"#cbb0e3"
],
"label": {
"normal": {
"textStyle": {
"color": "#eee"
}
}
}
},
"map": {
"itemStyle": {
"normal": {
"areaColor": "#f3f3f3",
"borderColor": "#516b91",
"borderWidth": 0.5
},
"emphasis": {
"areaColor": "rgba(165,231,240,1)",
"borderColor": "#516b91",
"borderWidth": 1
}
},
"label": {
"normal": {
"textStyle": {
"color": "#000"
}
},
"emphasis": {
"textStyle": {
"color": "rgb(81,107,145)"
}
}
}
},
"geo": {
"itemStyle": {
"normal": {
"areaColor": "#f3f3f3",
"borderColor": "#516b91",
"borderWidth": 0.5
},
"emphasis": {
"areaColor": "rgba(165,231,240,1)",
"borderColor": "#516b91",
"borderWidth": 1
}
},
"label": {
"normal": {
"textStyle": {
"color": "#000"
}
},
"emphasis": {
"textStyle": {
"color": "rgb(81,107,145)"
}
}
}
},
"categoryAxis": {
"axisLine": {
"show": true,
"lineStyle": {
"color": "#cccccc"
}
},
"axisTick": {
"show": false,
"lineStyle": {
"color": "#333"
}
},
"axisLabel": {
"show": true,
"textStyle": {
"color": "#999999"
}
},
"splitLine": {
"show": true,
"lineStyle": {
"color": [
"#eeeeee"
]
}
},
"splitArea": {
"show": false,
"areaStyle": {
"color": [
"rgba(250,250,250,0.05)",
"rgba(200,200,200,0.02)"
]
}
}
},
"valueAxis": {
"axisLine": {
"show": true,
"lineStyle": {
"color": "#cccccc"
}
},
"axisTick": {
"show": false,
"lineStyle": {
"color": "#333"
}
},
"axisLabel": {
"show": true,
"textStyle": {
"color": "#999999"
}
},
"splitLine": {
"show": true,
"lineStyle": {
"color": [
"#eeeeee"
]
}
},
"splitArea": {
"show": false,
"areaStyle": {
"color": [
"rgba(250,250,250,0.05)",
"rgba(200,200,200,0.02)"
]
}
}
},
"logAxis": {
"axisLine": {
"show": true,
"lineStyle": {
"color": "#cccccc"
}
},
"axisTick": {
"show": false,
"lineStyle": {
"color": "#333"
}
},
"axisLabel": {
"show": true,
"textStyle": {
"color": "#999999"
}
},
"splitLine": {
"show": true,
"lineStyle": {
"color": [
"#eeeeee"
]
}
},
"splitArea": {
"show": false,
"areaStyle": {
"color": [
"rgba(250,250,250,0.05)",
"rgba(200,200,200,0.02)"
]
}
}
},
"timeAxis": {
"axisLine": {
"show": true,
"lineStyle": {
"color": "#cccccc"
}
},
"axisTick": {
"show": false,
"lineStyle": {
"color": "#333"
}
},
"axisLabel": {
"show": true,
"textStyle": {
"color": "#999999"
}
},
"splitLine": {
"show": true,
"lineStyle": {
"color": [
"#eeeeee"
]
}
},
"splitArea": {
"show": false,
"areaStyle": {
"color": [
"rgba(250,250,250,0.05)",
"rgba(200,200,200,0.02)"
]
}
}
},
"toolbox": {
"iconStyle": {
"normal": {
"borderColor": "#999"
},
"emphasis": {
"borderColor": "#666"
}
}
},
"legend": {
"textStyle": {
"color": "#999999"
}
},
"tooltip": {
"axisPointer": {
"lineStyle": {
"color": "#ccc",
"width": 1
},
"crossStyle": {
"color": "#ccc",
"width": 1
}
}
},
"timeline": {
"lineStyle": {
"color": "#8fd3e8",
"width": 1
},
"itemStyle": {
"normal": {
"color": "#8fd3e8",
"borderWidth": 1
},
"emphasis": {
"color": "#8fd3e8"
}
},
"controlStyle": {
"normal": {
"color": "#8fd3e8",
"borderColor": "#8fd3e8",
"borderWidth": 0.5
},
"emphasis": {
"color": "#8fd3e8",
"borderColor": "#8fd3e8",
"borderWidth": 0.5
}
},
"checkpointStyle": {
"color": "#8fd3e8",
"borderColor": "rgba(138,124,168,0.37)"
},
"label": {
"normal": {
"textStyle": {
"color": "#8fd3e8"
}
},
"emphasis": {
"textStyle": {
"color": "#8fd3e8"
}
}
}
},
"visualMap": {
"color": [
"#516b91",
"#59c4e6",
"#a5e7f0"
]
},
"dataZoom": {
"backgroundColor": "rgba(0,0,0,0)",
"dataBackgroundColor": "rgba(255,255,255,0.3)",
"fillerColor": "rgba(167,183,204,0.4)",
"handleColor": "#a7b7cc",
"handleSize": "100%",
"textStyle": {
"color": "#333"
}
},
"markPoint": {
"label": {
"normal": {
"textStyle": {
"color": "#eee"
}
},
"emphasis": {
"textStyle": {
"color": "#eee"
}
}
}
}
});
}));

View File

@@ -0,0 +1,168 @@
{
"version": 1,
"themeName": "westeros",
"theme": {
"seriesCnt": "4",
"backgroundColor": "rgba(0,0,0,0)",
"titleColor": "#409eff",
"subtitleColor": "#93b7e3",
"textColorShow": false,
"textColor": "#333",
"markTextColor": "#eee",
"color": [
"#409eff",
"#59c4e6",
"#edafda",
"#93b7e3",
"#a5e7f0",
"#cbb0e3"
],
"borderColor": "#ccc",
"borderWidth": 0,
"visualMapColor": [
"#516b91",
"#59c4e6",
"#a5e7f0"
],
"legendTextColor": "#999999",
"kColor": "#edafda",
"kColor0": "transparent",
"kBorderColor": "#d680bc",
"kBorderColor0": "#8fd3e8",
"kBorderWidth": "2",
"lineWidth": "2",
"symbolSize": "6",
"symbol": "emptyCircle",
"symbolBorderWidth": "2",
"lineSmooth": true,
"graphLineWidth": 1,
"graphLineColor": "#aaa",
"mapLabelColor": "#000",
"mapLabelColorE": "rgb(81,107,145)",
"mapBorderColor": "#516b91",
"mapBorderColorE": "#516b91",
"mapBorderWidth": 0.5,
"mapBorderWidthE": 1,
"mapAreaColor": "#f3f3f3",
"mapAreaColorE": "rgba(165,231,240,1)",
"axes": [
{
"type": "all",
"name": "通用坐标轴",
"axisLineShow": true,
"axisLineColor": "#cccccc",
"axisTickShow": false,
"axisTickColor": "#333",
"axisLabelShow": true,
"axisLabelColor": "#999999",
"splitLineShow": true,
"splitLineColor": [
"#eeeeee"
],
"splitAreaShow": false,
"splitAreaColor": [
"rgba(250,250,250,0.05)",
"rgba(200,200,200,0.02)"
]
},
{
"type": "category",
"name": "类目坐标轴",
"axisLineShow": true,
"axisLineColor": "#333",
"axisTickShow": true,
"axisTickColor": "#333",
"axisLabelShow": true,
"axisLabelColor": "#333",
"splitLineShow": false,
"splitLineColor": [
"#ccc"
],
"splitAreaShow": false,
"splitAreaColor": [
"rgba(250,250,250,0.3)",
"rgba(200,200,200,0.3)"
]
},
{
"type": "value",
"name": "数值坐标轴",
"axisLineShow": true,
"axisLineColor": "#333",
"axisTickShow": true,
"axisTickColor": "#333",
"axisLabelShow": true,
"axisLabelColor": "#333",
"splitLineShow": true,
"splitLineColor": [
"#ccc"
],
"splitAreaShow": false,
"splitAreaColor": [
"rgba(250,250,250,0.3)",
"rgba(200,200,200,0.3)"
]
},
{
"type": "log",
"name": "对数坐标轴",
"axisLineShow": true,
"axisLineColor": "#333",
"axisTickShow": true,
"axisTickColor": "#333",
"axisLabelShow": true,
"axisLabelColor": "#333",
"splitLineShow": true,
"splitLineColor": [
"#ccc"
],
"splitAreaShow": false,
"splitAreaColor": [
"rgba(250,250,250,0.3)",
"rgba(200,200,200,0.3)"
]
},
{
"type": "time",
"name": "时间坐标轴",
"axisLineShow": true,
"axisLineColor": "#333",
"axisTickShow": true,
"axisTickColor": "#333",
"axisLabelShow": true,
"axisLabelColor": "#333",
"splitLineShow": true,
"splitLineColor": [
"#ccc"
],
"splitAreaShow": false,
"splitAreaColor": [
"rgba(250,250,250,0.3)",
"rgba(200,200,200,0.3)"
]
}
],
"axisSeperateSetting": false,
"toolboxColor": "#999",
"toolboxEmpasisColor": "#666",
"tooltipAxisColor": "#ccc",
"tooltipAxisWidth": 1,
"timelineLineColor": "#8fd3e8",
"timelineLineWidth": 1,
"timelineItemColor": "#8fd3e8",
"timelineItemColorE": "#8fd3e8",
"timelineCheckColor": "#8fd3e8",
"timelineCheckBorderColor": "rgba(138,124,168,0.37)",
"timelineItemBorderWidth": 1,
"timelineControlColor": "#8fd3e8",
"timelineControlBorderColor": "#8fd3e8",
"timelineControlBorderWidth": 0.5,
"timelineLabelColor": "#8fd3e8",
"datazoomBackgroundColor": "rgba(0,0,0,0)",
"datazoomDataColor": "rgba(255,255,255,0.3)",
"datazoomFillColor": "rgba(167,183,204,0.4)",
"datazoomHandleColor": "#a7b7cc",
"datazoomHandleWidth": "100",
"datazoomLabelColor": "#333"
}
}

View File

@@ -0,0 +1,53 @@
<template>
<el-dropdown class='international' @command="handleSetLanguage">
<div>
<span class="el-dropdown-link"><i class="fa fa-language fa-lg"></i>&nbsp;{{language}}<i class="el-icon-arrow-down el-icon--right"></i>
</span>
</div>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="cn">中文</el-dropdown-item>
<el-dropdown-item command="en">English</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template>
<script>
export default {
name: 'langSelect',
data () {
return {
language: ''
}
},
mounted () {
const _lang = localStorage.lang || 'cn'
this.getLanguage(_lang)
},
methods: {
handleSetLanguage (lang) {
this.$i18n.locale = lang
localStorage.setItem('lang', lang)
this.getLanguage(lang)
},
getLanguage (val) {
if (val === 'cn') {
this.language = '中文'
}
if (val === 'en') {
this.language = 'English'
}
}
}
}
</script>
<style>
.international .el-dropdown-link { cursor: pointer; color: #666666; font-size: 14px; }
.el-icon-arrow-down { font-size: 14px; }
</style>
<style scoped>
.international-icon {
font-size: 20px;
cursor: pointer;
vertical-align: -5px !important;
}
</style>

View File

@@ -0,0 +1,180 @@
const defaultConfig = {
width: '100%',
height: 600,
path: './static/markdown/lib/',
// theme: 'dark',
previewTheme: 'default',
editorTheme: 'pastel-on-dark',
// markdown: '默认填充内容', // 默认填充内容
lineWrapping: true, // 编辑框不换行
codeFold: true, // 代码折叠
placeholder: '请输入...',
syncScrolling: true,
saveHTMLToTextarea: true, // 保存 HTML 到 Textarea
searchReplace: true,
watch: true, // 实时预览
// htmlDecode: "style,script,iframe|on*", // 开启 HTML 标签解析,为了安全性,默认不开启
toolbar: true, // 工具栏
previewCodeHighlight: true, // 预览 HTML 的代码块高亮,默认开启
emoji: true,
taskList: true,
tocm: true, // Using [TOCM]
tex: true, // 开启科学公式TeX语言支持默认关闭
flowChart: true, // 开启流程图支持,默认关闭
sequenceDiagram: true, // 开启时序/序列图支持,默认关闭,
// dialogLockScreen: false, // 设置弹出层对话框不锁屏全局通用默认为true
// dialogShowMask: false, // 设置弹出层对话框显示透明遮罩层全局通用默认为true
// dialogDraggable: false, // 设置弹出层对话框不可拖动全局通用默认为true
// dialogMaskOpacity: 0.4, // 设置透明遮罩层的透明度全局通用默认值为0.1
// dialogMaskBgColor: "#000", // 设置透明遮罩层的背景颜色,全局通用,默认为#fff
imageUpload: true,
imageFormats: ['jpg', 'jpeg', 'gif', 'png', 'bmp', 'webp'],
imageUploadURL: '../../assets/uploadImage'
// onload: function() {
// // this.fullscreen();
// // this.unwatch();
// // this.watch().fullscreen();
// // this.setMarkdown("#PHP");
// // this.width("100%");
// // this.height(480);
// // this.resize("100%", 640);
// },
}
const codeThemes = [
{
label: 'monokai',
value: 'monokai.min.css'
},
{
label: 'atelier-cave-dark',
value: 'atelier-cave-dark.min.css'
},
{
label: 'atelier-cave-light',
value: 'atelier-cave-light.min.css'
},
{
label: 'atelier-dune-dark',
value: 'atelier-dune-dark.min.css'
},
{
label: 'atelier-dune-light',
value: 'atelier-dune-light.min.css'
},
{
label: 'atelier-estuary-dark',
value: 'atelier-estuary-dark.min.css'
},
{
label: 'atelier-estuary-light',
value: 'atelier-estuary-light.min.css'
},
{
label: 'atelier-forest-dark',
value: 'atelier-forest-dark.min.css'
},
{
label: 'atelier-forest-light',
value: 'atelier-forest-light.min.css'
},
{
label: 'atelier-heath-dark',
value: 'atelier-heath-dark.min.css'
},
{
label: 'atelier-heath-light',
value: 'atelier-heath-light.min.css'
},
{
label: 'atelier-lakeside-dark',
value: 'atelier-lakeside-dark.min.css'
},
{
label: 'atelier-lakeside-light',
value: 'atelier-lakeside-light.min.css'
},
{
label: 'atelier-plateau-dark',
value: 'atelier-plateau-dark.min.css'
},
{
label: 'atelier-plateau-light',
value: 'atelier-plateau-light.min.css'
},
{
label: 'atelier-savanna-dark',
value: 'atelier-savanna-dark.min.css'
},
{
label: 'atelier-savanna-light',
value: 'atelier-savanna-light.min.css'
},
{
label: 'atelier-seaside-dark',
value: 'atelier-seaside-dark.min.css'
},
{
label: 'atelier-seaside-light',
value: 'atelier-seaside-light.min.css'
},
{
label: 'atelier-sulphurpool-dark',
value: 'atelier-sulphurpool-dark.min.css'
},
{
label: 'atelier-sulphurpool-light',
value: 'atelier-sulphurpool-light.min.css'
},
{
label: 'github',
value: 'github.min.css'
},
{
label: 'github-v2',
value: 'github-v2.min.css'
},
{
label: 'hemisu-dark',
value: 'hemisu-dark.min.css'
},
{
label: 'hemisu-light',
value: 'hemisu-light.min.css'
},
{
label: 'tomorrow',
value: 'tomorrow.min.css'
},
{
label: 'tomorrow-night',
value: 'tomorrow-night.min.css'
},
{
label: 'tomorrow-night-blue',
value: 'tomorrow-night-blue.min.css'
},
{
label: 'tomorrow-night-bright',
value: 'tomorrow-night-bright.min.css'
},
{
label: 'tomorrow-night-eighties',
value: 'tomorrow-night-eighties.min.css'
},
{
label: 'tranquil-heart',
value: 'previewTheme-xu.css'
},
{
label: 'vibrant-ink',
value: 'vibrant-ink.min.css'
},
{
label: 'pastel-on-dark-xu',
value: 'pastel-on-dark-xu.css'
}
]
export {
defaultConfig,
codeThemes
}

View File

@@ -0,0 +1,100 @@
<template>
<div class="markdownBox">
<link rel="stylesheet" href="./static/markdown/css/editormd.min.css">
<link rel="stylesheet" href="./static/markdown/css/googleCodePrettifyThemes/previewTheme-xu.css">
<div :id="editorId"></div>
</div>
</template>
<script>
import scriptjs from 'scriptjs'
import { defaultConfig, codeThemes } from './config.editor'
export default {
name: 'markdown-editor',
props: {
editorId: {
'type': String,
'default': 'markdown-editor'
},
onchange: { // 内容改变时回调返回html, markdown, text
type: Function
},
config: { // 编辑器配置
type: Object
},
codeTheme: { // 代码高亮主题
'type': String,
'default': 'vibrant-ink.min.css'
},
initData: {
'type': String
},
initDataDelay: {
'type': Number, // 延迟初始化数据时间,单位毫秒
'default': 0
}
},
data: function () {
return {
editor: null,
codeThemes,
editorLoaded: false
}
},
methods: {
fetchScript: function (url) {
return new Promise((resolve) => {
scriptjs(url, () => {
resolve()
})
})
},
getConfig: function () {
return {...defaultConfig, ...this.config }
},
setMarkdown: function (val) {
let editor = window.editormd(this.editorId, this.getConfig())
editor.setMarkdown(val)
},
initEditor: function () {
(async () => {
await this.fetchScript('./static/markdown/jquery.min.js')
await this.fetchScript('./static/markdown/editormd.min.js')
// await this.fetchScript('./static/editor.md/editormd.js');
this.$nextTick(() => {
let editor = window.editormd(this.editorId, this.getConfig())
editor.on('load', () => {
setTimeout(() => { // hack bug: 一个页面多个编辑器只能初始化其中一个数据问题
this.editorLoaded = true
this.initData && editor.setMarkdown(this.initData)
}, this.initDataDelay)
})
this.onchange && editor.on('change', () => {
let html = editor.getPreviewedHTML()
this.onchange({
markdown: editor.getMarkdown(),
html: html,
text: window.$(html).text()
})
})
this.editor = editor
})
})()
}
},
mounted: function () {
this.initEditor()
},
watch: {
'initData': function (newVal) {
if (newVal) {
this.editorLoaded && this.editor.setMarkdown(newVal)
}
}
}
}
</script>
<style scoped>
</style>

19
src/i18n/i18n.js Normal file
View File

@@ -0,0 +1,19 @@
/**
* Created by WebStorm.
* User: nirongxu
* Date: 2018/12/8
* Description: 文件描述
*/
import Vue from 'vue'
import locale from 'element-ui/lib/locale'
import VueI18n from 'vue-i18n'
import messages from './lang'
Vue.use(VueI18n)
const i18n = new VueI18n({
locale: localStorage.lang || 'cn',
messages
})
locale.i18n((key, value) => i18n.t(key, value))
export default i18n

62
src/i18n/lang/cn.js Normal file
View File

@@ -0,0 +1,62 @@
/**
* Created by WebStorm.
* User: nirongxu
* Date: 2018/12/8
* Description: 文件描述
*/
import zhLocale from 'element-ui/lib/locale/lang/zh-CN'
const cn = {
routeNmae: {
home: '主页',
article: '文章管理',
publishArticle: '发表文章',
publishArticleEditor: '发表文章-富文本',
icon: '图标',
builtInIcon: '内置图标',
shuttleBox: '穿梭框',
demoShuttle: '穿梭框demo',
permissions: '权限管理',
pageControl: '页面权限',
btnControl: '按钮权限',
table: '表格',
multiDataTable: '多选数据表格',
filterTable: '筛选表格',
dragSort: '拖拽排序',
upload: '上传',
fileUpload: '文件上传',
editor: '编辑器',
markdown: 'markdown',
wangeditor: 'wangeditor',
multiDirectory: '多级目录',
'menu2-1': '二级-1',
'menu2-2': '二级-2',
'menu2-3': '二级-3',
'menu3-1': '三级-1',
'menu3-2': '三级-2',
'menu3-3': '三级-3',
'menu4-1': '四级-1',
'menu4-2': '四级-2',
'menu5-1': '五级-1',
systemSettings: '系统设置',
navMenu : '导航菜单',
},
rightMenu: {
close: '关闭',
closeOther: '关闭其他',
closeAll: '全部关闭'
},
role: {
superAdmin: '超级管理员',
admin: '管理员',
ordinary: '普通用户'
},
userDropdownMenu: {
basicInfor: '基本资料',
changePassword: '修改密码',
logout: '退出'
},
...zhLocale // 合并element-ui内置翻译
}
export default cn

63
src/i18n/lang/en.js Normal file
View File

@@ -0,0 +1,63 @@
/**
* Created by WebStorm.
* User: nirongxu
* Date: 2018/12/8
* Description: 文件描述
*/
import enLocale from 'element-ui/lib/locale/lang/en'
const en = {
routeNmae: {
home: 'home',
article: 'article',
publishArticle: 'publishArticle',
publishArticleEditor: 'publishArticleEditor',
icon: 'icon',
builtInIcon: 'builtInIcon',
shuttleBox: 'shuttleBox',
demoShuttle: 'demoShuttle',
permissions: 'permissions',
pageControl: 'pageControl',
btnControl: 'btnControl',
table: 'table',
multiDataTable: 'multiDataTable',
filterTable: 'filterTable',
dragSort: 'dragSort',
upload: 'upload',
fileUpload: 'fileUpload',
editor: 'editor',
markdown: 'markdown',
wangeditor: 'wangeditor',
multiDirectory: 'multiDirectory',
'menu2-1': 'menu2-1',
'menu2-2': 'menu2-2',
'menu2-3': 'menu2-3',
'menu3-1': 'menu3-1',
'menu3-2': 'menu3-2',
'menu3-3': 'menu3-3',
'menu4-1': 'menu4-1',
'menu4-2': 'menu4-2',
'menu5-1': 'menu5-1',
systemSettings: 'systemSettings',
navMenu : 'navMenu',
},
rightMenu: {
close: 'close',
closeOther: 'closeOther',
closeAll: 'closeAll'
},
role: {
superAdmin: 'superAdmin',
admin: 'admin',
ordinary: 'ordinary'
},
userDropdownMenu: {
basicInfor: 'basicInfor',
changePassword: 'changePassword',
logout: 'logout'
},
...enLocale // 合并element-ui内置翻译
}
export default en

13
src/i18n/lang/index.js Normal file
View File

@@ -0,0 +1,13 @@
/**
* Created by WebStorm.
* User: nirongxu
* Date: 2018/12/8
* Description: 文件描述
*/
import en from './en'
import cn from './cn'
export default {
en,
cn
}

72
src/main.js Normal file
View File

@@ -0,0 +1,72 @@
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from './btnPermission'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
import './assets/iconfont/iconfont.css'
import 'font-awesome/css/font-awesome.css'
import App from './App.vue'
import router from './router'
import store from './vuex'
import i18n from './i18n/i18n'
Vue.config.productionTip = false
Vue.use(ElementUI)
// 获取角色信息,根据用户权限动态加载路由
router.beforeEach((to, from, next) => {
console.log(store.getters.token)
// debugger
if (store.getters.token) {
store.dispatch('setToken', store.getters.token)
if (to.path === '/login') {
next({path: '/'})
} else {
if (!store.getters.info.role) {
// const role = ['/markdown', '/erji', '/erji2', '/siji', '/wuji']
!async function getAddRouters () {
// 省略 axios 请求代码 通过 token 向后台请求用户权限等信息,这里用假数据赋值
await store.dispatch('getInfo', {
role: 'superAdmin',
permissions: '超级管理员'
})
await store.dispatch('newRoutes', store.getters.info.role)
console.log(store.getters.addRouters)
await router.addRoutes(store.getters.addRouters)
next({path: '/index'})
}()
} else {
let is404 = to.matched.some(record => {
if(record.meta.role){
return record.meta.role.indexOf(store.getters.info.role) === -1
}
})
if(is404){
next({path: '/404'})
return false
}
next()
}
}
} else {
if (to.path === '/login') {
next()
}
next({path: '/login'})
}
})
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
store,
i18n,
render: h => h(App),
components: {App},
template: '<App/>'
})

203
src/markData.js Normal file
View File

@@ -0,0 +1,203 @@
let initData = '# vue-xuAdmin 初始值\n' +
'\n' +
'### 多语言代码高亮 Codes\n' +
'\n' +
'#### 行内代码 Inline code\n' +
'\n' +
'执行命令:`npm install marked`\n' +
'\n' +
'#### 缩进风格\n' +
'\n' +
'即缩进四个空格,也做为实现类似`<pre>`预格式化文本(Preformatted Text)的功能。\n' +
'\n' +
' <?php\n' +
' echo "Hello world!";\n' +
' ?>\n' +
' \n' +
'预格式化文本:\n' +
'\n' +
' | First Header | Second Header |\n' +
' | ------------- | ------------- |\n' +
' | Content Cell | Content Cell |\n' +
' | Content Cell | Content Cell |\n' +
'#### java代码\n' +
'\n' +
'```java\n' +
'public class HelloWorld {\n' +
' public static void main(String[] args) {\n' +
' System.out.println("Hello World");\n' +
' }\n' +
'}\n' +
'```\n' +
'#### JS代码 \n' +
'\n' +
'```javascript\n' +
'function test(){\n' +
'\tconsole.log("Hello world!");\n' +
'}\n' +
' \n' +
'(function(){\n' +
' var box = function(){\n' +
' return box.fn.init();\n' +
' };\n' +
'\n' +
' box.prototype = box.fn = {\n' +
' init : function(){\n' +
' console.log(\'box.init()\');\n' +
'\n' +
'\t\t\treturn this;\n' +
' },\n' +
'\n' +
'\t\tadd : function(str){\n' +
'\t\t\talert("add", str);\n' +
'\n' +
'\t\t\treturn this;\n' +
'\t\t},\n' +
'\n' +
'\t\tremove : function(str){\n' +
'\t\t\talert("remove", str);\n' +
'\n' +
'\t\t\treturn this;\n' +
'\t\t}\n' +
' };\n' +
' \n' +
' box.fn.init.prototype = box.fn;\n' +
' \n' +
' window.box =box;\n' +
'})();\n' +
'\n' +
'var testBox = box();\n' +
'testBox.add("jQuery").remove("jQuery");\n' +
'```\n' +
'\n' +
'#### HTML代码 HTML codes\n' +
'\n' +
'```html\n' +
'<!DOCTYPE html>\n' +
'<html>\n' +
' <head>\n' +
' <mate charest="utf-8" />\n' +
' <title>Hello world!</title>\n' +
' </head>\n' +
' <body>\n' +
' <h1>Hello world!</h1>\n' +
' </body>\n' +
'</html>\n' +
'```\n### 列表 Lists\n' +
'\n' +
'#### 无序列表减号Unordered Lists (-)\n' +
' \n' +
'- 列表一\n' +
'- 列表二\n' +
'- 列表三\n' +
' \n' +
'#### 无序列表星号Unordered Lists (*)\n' +
'\n' +
'* 列表一\n' +
'* 列表二\n' +
'* 列表三\n' +
'\n' +
'#### 无序列表加号和嵌套Unordered Lists (+)\n' +
' \n' +
'+ 列表一\n' +
'+ 列表二\n' +
' + 列表二-1\n' +
' + 列表二-2\n' +
' + 列表二-3\n' +
'+ 列表三\n' +
' * 列表一\n' +
' * 列表二\n' +
' * 列表三\n' +
'\n' +
'#### 有序列表 Ordered Lists (-)\n' +
' \n' +
'1. 第一行\n' +
'2. 第二行\n' +
'3. 第三行\n' +
'\n' +
'#### GFM task list\n' +
'\n' +
'- [x] GFM task list 1\n' +
'- [x] GFM task list 2\n' +
'- [ ] GFM task list 3\n' +
' - [ ] GFM task list 3-1\n' +
' - [ ] GFM task list 3-2\n' +
' - [ ] GFM task list 3-3\n' +
'- [ ] GFM task list 4\n' +
' - [ ] GFM task list 4-1\n' +
' - [ ] GFM task list 4-2\n' +
' \n' +
'----### 绘制表格 Tables\n' +
'\n' +
'| 项目 | 价格 | 数量 |\n' +
'| -------- | -----: | :----: |\n' +
'| 计算机 | $1600 | 5 |\n' +
'| 手机 | $12 | 12 |\n' +
'| 管线 | $1 | 234 |\n' +
' \n' +
'\n' +
'| Function name | Description |\n' +
'| ------------- | ------------------------------ |\n' +
'| `help()` | Display the help window. |\n' +
'| `destroy()` | **Destroy your computer!** |\n' +
'\n' +
'| Left-Aligned | Center Aligned | Right Aligned |\n' +
'| :------------ |:---------------:| -----:|\n' +
'| col 3 is | some wordy text | $1600 |\n' +
'| col 2 is | centered | $12 |\n' +
'| zebra stripes | are neat | $1 |\n' +
'\n' +
'\n' +
' \n' +
'### 科学公式 TeX(KaTeX)\n' +
' \n' +
'$$E=mc^2$$\n' +
'\n' +
'行内的公式$$E=mc^2$$行内的公式,行内的$$E=mc^2$$公式。\n' +
'\n' +
'$$\\(\\sqrt{3x-1}+(1+x)^2\\)$$\n' +
' \n' +
'$$\\sin(\\alpha)^{\\theta}=\\sum_{i=0}^{n}(x^i + \\cos(f))$$\n多行公式\n' +
'\n' +
'```math\n' +
'\\displaystyle\n' +
'\\left( \\sum\\_{k=1}^n a\\_k b\\_k \\right)^2\n' +
'\\leq\n' +
'\\left( \\sum\\_{k=1}^n a\\_k^2 \\right)\n' +
'\\left( \\sum\\_{k=1}^n b\\_k^2 \\right)\n' +
'```\n```katex\n' +
'\\displaystyle \n' +
' \\frac{1}{\n' +
' \\Bigl(\\sqrt{\\phi \\sqrt{5}}-\\phi\\Bigr) e^{\n' +
' \\frac25 \\pi}} = 1+\\frac{e^{-2\\pi}} {1+\\frac{e^{-4\\pi}} {\n' +
' 1+\\frac{e^{-6\\pi}}\n' +
' {1+\\frac{e^{-8\\pi}}\n' +
' {1+\\cdots} }\n' +
' } \n' +
' }\n' +
'```' +
'\n### 绘制流程图 Flowchart\n' +
'\n' +
'```flow\n' +
'st=>start: 用户登陆\n' +
'op=>operation: 登陆操作\n' +
'cond=>condition: 登陆成功 Yes or No?\n' +
'e=>end: 进入后台\n' +
'\n' +
'st->op->cond\n' +
'cond(yes)->e\n' +
'cond(no)->op\n' +
'```\n' +
' \n' +
'### 绘制序列图 Sequence Diagram\n' +
' \n' +
'```seq\n' +
'Andrew->China: Says Hello \n' +
'Note right of China: China thinks\\nabout it \n' +
'China-->Andrew: How are you? \n' +
'Andrew->>China: I am good thanks!\n' +
'```\n' +
'\n' +
'### End'
export default initData

286
src/page404.vue Normal file
View File

@@ -0,0 +1,286 @@
<template>
<div class="page404">
<div class="code">
<p>ERROR 404</p>
<p>访问资源未找到</p>
</div>
<div class="road">
<div class="shadow">
<div class="shelt">
<div class="head">
<div class="eyes">
<div class="lefteye">
<div class="eyeball"></div>
<div class="eyebrow"></div>
</div>
<div class="righteye">
<div class="eyeball"></div>
<div class="eyebrow"></div>
</div>
</div>
</div>
</div>
<div class="hat"></div>
<div class="bubble">
<a href="/">返回主页?</a>
</div>
</div>
<p>PAGE NOT FOUND</p>
</div>
</div>
</template>
<script>
import $ from 'jquery'
export default {
name: 'page404',
mounted () {
var parallel = 17
var headHeight = 150
var opacity = 0
var eyeBrowHeight = 0
var step = 1
var timer_show
var timer_eyebrow
document.onmousemove = mouseMove
function mouseMove (e) {
/* 眼球转动 */
}
function startAnimation () {
timer_show = setInterval(function () {
parallel = parallel - 0.3
headHeight = headHeight - 2.5
opacity = (17 - parallel) / 17
if (parallel > 0) {
$('.head').css('top', headHeight + 'px')
$('.hat').css('transform', 'rotate(' + parallel + 'deg)')
$('.bubble').css('opacity', opacity)
} else {
window.clearInterval(timer_show)
timer_eyebrow = setInterval(function () {
eyeBrowHeight += step
$('.lefteye .eyebrow').css('clip', 'rect(0px 38px ' + eyeBrowHeight + 'px 0px)')
$('.righteye .eyebrow').css('clip', 'rect(0px 38px ' + eyeBrowHeight + 'px 0px)')
if (eyeBrowHeight % 19 === 0) { step = -step }
}, 10)
}
}, 55)
window.setTimeout(function () {
window.clearInterval(timer_eyebrow)
timer_show = setInterval(function () {
parallel = parallel + 0.3
headHeight = headHeight + 2.5
opacity = (17 - parallel) / 17
if (parallel <= 17) {
$('.head').css('top', headHeight + 'px')
$('.hat').css('transform', 'rotate(' + parallel + 'deg)')
// $('.code p').css('opacity',opacity);
$('.bubble').css('opacity', opacity)
} else {
window.clearInterval(timer_show)
startAnimation()
}
}, 55)
}, 1000 * 6)
}
startAnimation()
}
}
</script>
<style scoped>
body, div, p, a{
margin: 0px;
padding: 0px;
}
p{
text-decoration: none;
user-select: none;
}
html, body{
width: 100%;
height: 100%;
}
.page404{
background: linear-gradient(#c7c8cf,#e8e8e9,#c7c8cf) !important;
overflow: hidden;
}
.code{
display: block;
width: 100%;
height: 120px;
line-height: 120px;
}
.code p{
height: inherit;
line-height: inherit;
text-align: center;
font-family: BalboaWide Bold;
font-size: 50px;
color: #697a8a;
opacity: 1;
}
.road{
width: 100%;
height: 600px;
}
.road .shadow{
position: relative;
margin: auto;
margin-top: 25%;
width: 330px;
height: 70px;
border:0px;
background: linear-gradient(#777373,#3c3c3c);
box-shadow: 0px 3px 10px 2px #464646, 0px -3px 10px 2px #3a3939 inset;
border-radius: 100%;
}
.road p{
display: block;
margin-top: 50px;
height: inherit;
line-height: inherit;
text-align: center;
font-family: BalboaWide Bold;
font-size: 30px;
color: #697a8a;
opacity: 1;
}
.road .shadow .bubble{
display: block;
position: absolute;
top: -180px;
left: 350px;
width: 246px;
height: 179px;
background-image: url(assets/img404/bubble.png);
background-repeat: no-repeat;
text-align: center;
}
.road .shadow .bubble a{
line-height: 140px;
font-family: "microsoft yahei";
font-size: 1.5em;
color: #F8F8F5;
letter-spacing: 1px;
text-decoration: none;
transition: 1s;
user-select:none;
}
.road .shadow .bubble a:hover{
color: #FF8C00;
}
.road .shadow .shelt{
position: absolute;
margin: auto;
margin-top: -80px;
width: 330px;
height: 150px;
border:0px;
border-radius: 100%;
overflow: hidden;
background: transparent;
}
.road .shadow .head{
position: absolute;
left: 50%;
margin-left: -60px;
top: 150px;
width: 120px;
height: 300px;
border: 0px;
border-radius: 100% 100% 0 0;
background-color: #292d38;
}
.road .shadow .head .eyes{
width: 100%;
height: 50px;
margin-top: 70px;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
justify-content: space-around;
}
.road .shadow .head .eyes .lefteye,.road .shadow .head .eyes .righteye{
position: relative;
width: 38px;
height: 38px;
border-radius: 100%;
background-color: #f1f2f4;
}
.road .shadow .head .eyes .lefteye .eyebrow{
position: absolute;
width: 38px;
left: 0px;
top: 0px;
height: 19px;
border-radius: 19px 19px 0 0;
background-color:#4c5465;
clip: rect(0px 38px 0px 0px);
}
.road .shadow .head .eyes .righteye .eyebrow{
position: absolute;
width: 38px;
left: 0px;
top: 0px;
height: 19px;
border-radius: 19px 19px 0 0;
background-color:#4c5465;
clip: rect(0px 38px 0px 0px);
}
.road .shadow .head .eyes .lefteye .eyeball{
position: absolute;
width: 10px;
left: 50%;
top: 50%;
margin-top: -5px;
margin-left: -5px;
height: 10px;
border-radius: 100%;
background-color:#292d38 ;
}
.road .shadow .head .eyes .righteye .eyeball{
position: absolute;
width: 10px;
left: 50%;
top: 50%;
margin-top: -5px;
margin-left: -5px;
height: 10px;
border-radius: 100%;
background-color:#292d38 ;
}
.road .shadow .hat{
position: absolute;
top: -297px;
left: -8px;
width: 330px;
height: 330px;
background: url(assets/img404/sign.png) no-repeat;
transform-origin: left bottom;
transform: rotate(17deg);
}
</style>

315
src/router/index.js Normal file
View File

@@ -0,0 +1,315 @@
import en from '../i18n/lang/en'
import Vue from 'vue'
import Router from 'vue-router'
import CommerViews from '@/views/commerViews'
import Login from '@/views/login/index'
import Layout from '@/views/layout/layout'
import HomeMain from '@/views/index/mainIndex'
// 不是必须加载的组件使用懒加载
const Icon = () => import('@/views/icon/index')
const Erji = () => import('@/views/duoji/erji')
const Erji2 = () => import('@/views/duoji/erji2')
const Sanji = () => import('@/views/duoji/sanji')
const Sanji2 = () => import('@/views/duoji/sanji2')
const Siji = () => import('@/views/duoji/siji')
const Wuji = () => import('@/views/duoji/wuji')
const Transfer = () => import('@/views/transfer/transfer')
const DataTable = () => import('@/views/table/dataTables')
const FilterTable = () => import('@/views/table/filterTable')
const DragTable = () => import('@/views/table/dragTabe')
const Upload = () => import('@/views/upload/upload')
const Markdown = () => import('@/views/editor/markdownView')
const WangeditorView = () => import('@/views/editor/wangeditorView')
const NotFound = () => import('@/page404')
const AddArticle = () => import('@/views/article/addArticle')
const AddArticleEditor = () => import('@/views/article/addArticleEditor')
const NavClassify = () => import('@/views/syssetting/navClassify')
const pagePermissions = () => import('@/views/permissions/pagePermissions')
const btnPermissions = () => import('@/views/permissions/btnPermissions')
Vue.use(Router)
let routeNmae = en.routeNmae
let defaultRouter = [
{ path: '/',
redirect: '/index',
hidden: true,
children: []
},
{
path: '/login',
component: Login,
name: '',
hidden: true,
children: []
},
{
path: '/index',
iconCls: 'fa fa-dashboard', // 图标样式class
name: routeNmae.home,
component: Layout,
alone: true,
children: [
{
path: '/index',
iconCls: 'fa fa-dashboard', // 图标样式class
name: '主页',
component: HomeMain,
children: []
}
]
},
{
path: '/404',
component: NotFound,
name: '404',
hidden: true,
children: []
},
]
let addRouter = [
{
path: '/',
iconCls: 'el-icon-tickets', // 图标样式class
name: routeNmae.article,
component: Layout,
children: [
{
path: '/addArticle',
iconCls: 'el-icon-edit-outline', // 图标样式class
name: routeNmae.publishArticle,
component: AddArticle,
children: []
},
{
path: '/addArticleEditor',
iconCls: 'el-icon-edit-outline', // 图标样式class
name: routeNmae.publishArticleEditor,
component: AddArticleEditor,
children: []
}
]
},
{
path: '/',
iconCls: 'fa fa-paw', // 图标样式class
name: routeNmae.icon,
component: Layout,
children: [
{
path: '/icon',
iconCls: 'fa fa-life-ring', // 图标样式class
name: routeNmae.builtInIcon,
component: Icon,
children: []
}
]
},
{
path: '/',
iconCls: 'fa fa-exchange', // 图标样式class
name: routeNmae.shuttleBox,
component: Layout,
children: [
{
path: '/transfer',
iconCls: 'fa fa-sign-in', // 图标样式class
name: routeNmae.demoShuttle,
component: Transfer,
children: []
}
]
},
{
path: '/',
iconCls: 'fa fa-universal-access', // 图标样式class
name: routeNmae.permissions,
component: Layout,
children: [
{
path: '/pagePermissions',
iconCls: 'fa fa-expeditedssl', // 图标样式class
name: routeNmae.pageControl,
component: pagePermissions,
children: []
},
{
path: '/btnPermissions',
iconCls: 'fa fa-toggle-on', // 图标样式class
name: routeNmae.btnControl,
component: btnPermissions,
children: []
}
]
},
{
path: '/',
iconCls: 'fa fa-newspaper-o', // 图标样式class
name: routeNmae.table,
component: Layout,
children: [
{
path: '/dataTable',
iconCls: 'fa fa-sliders', // 图标样式class
name: routeNmae.multiDataTable,
component: DataTable,
children: []
},
{
path: '/filterTable',
iconCls: 'fa fa-sort-amount-asc', // 图标样式class
name: routeNmae.filterTable,
component: FilterTable,
children: []
},
{
path: '/dragTabe',
iconCls: 'fa fa-hand-stop-o', // 图标样式class
name: routeNmae.dragSort,
component: DragTable,
children: []
}
]
},
{
path: '/',
iconCls: 'fa fa-server',
name: routeNmae.multiDirectory,
component: Layout,
children: [
{
path: '/erji1',
iconCls: 'fa fa-server',
name: routeNmae['menu2-1'],
component: Erji,
children: []
},
{
path: '/erji2',
iconCls: 'fa fa-server',
name: routeNmae['menu2-2'],
component: Erji2,
children: []
},
{
path: '/erji3',
iconCls: 'fa fa-server',
name: routeNmae['menu2-3'],
component: CommerViews, // 无限极菜单的容器
children: [
{
path: '/sanji1',
iconCls: 'fa fa-server',
name: routeNmae['menu3-1'],
component: Sanji,
children: []
},
{
path: '/sanji2',
iconCls: 'fa fa-server',
name: routeNmae['menu3-2'],
component: Sanji2,
children: []
},
{
path: '/sanji3',
iconCls: 'fa fa-server',
name: routeNmae['menu3-3'],
component: CommerViews,
children: [
{
path: '/siji',
iconCls: 'fa fa-server',
name: routeNmae['menu4-1'],
component: Siji,
children: []
},
{
path: '/siji1',
iconCls: 'fa fa-server',
name: routeNmae['menu4-2'],
component: CommerViews,
children: [
{
path: '/wuji',
iconCls: 'fa fa-server',
name: routeNmae['menu5-1'],
component: Wuji,
children: []
}
]
}
]
}
]
}
]
},
{
path: '/',
iconCls: 'fa fa-cloud-upload', // 图标样式class
name: routeNmae.upload,
component: Layout,
meta: {role: ['superAdmin']},
children: [
{
path: '/upload',
iconCls: 'el-icon-upload2', // 图标样式class
name: routeNmae.fileUpload,
component: Upload,
children: []
}
]
},
{
path: '/',
iconCls: 'el-icon-edit', // 图标样式class
name: routeNmae.editor,
component: Layout,
meta: {role: ['superAdmin', 'admin']},
children: [
{
path: '/markdown',
iconCls: 'fa fa-file-code-o', // 图标样式class
name: routeNmae.markdown,
component: Markdown,
children: []
},
{
path: '/wangeditor',
iconCls: 'fa fa-file-code-o', // 图标样式class
name: routeNmae.wangeditor,
component: WangeditorView,
children: []
}
]
},
{
path: '/',
iconCls: 'el-icon-setting', // 图标样式class
name: routeNmae.systemSettings,
component: Layout,
meta: {role: ['superAdmin']},
children: [
{
path: '/navClassifies',
iconCls: 'el-icon-menu', // 图标样式class
name: routeNmae.navMenu,
component: NavClassify,
children: []
}
]
},
{ path: '*',
redirect: '/404',
hidden: true,
children: []
},
]
export default new Router({
routes: defaultRouter
})
export {defaultRouter, addRouter}

View File

@@ -0,0 +1,93 @@
<template>
<div class="addArticle">
<el-form ref="article" :model="article" label-width="80px">
<el-form-item label="文章标题">
<el-input v-model="article.title"></el-input>
</el-form-item>
<el-form-item label="标签">
<el-autocomplete
class="inline-input"
v-model="article.tag"
:fetch-suggestions="querySearch"
placeholder="请输入内容"
@select="handleSelect"
></el-autocomplete>
</el-form-item>
<el-form-item label="是否置顶">
<el-switch v-model="article.top"></el-switch>
</el-form-item>
</el-form>
<Markdown :onchange="change" v-bind:initData="initData"></Markdown>
<el-row type="flex" class="row-bg" justify="end">
<el-button class="subBtn" type="primary" @click="submitArticle">发布</el-button>
</el-row>
</div>
</template>
<script>
import Markdown from '../../components/markdown/markdown-editor'
import initData from '../../markData.js'
export default {
name: 'addArticle',
data () {
return {
article: {
title: '',
tag: '',
top: false,
content: {}
},
initData: initData,
restaurants: []
}
},
components: {Markdown},
methods: {
change () {
console.log(arguments[0], this.article)
this.article.content = arguments[0]
},
querySearch (queryString, cb) {
var restaurants = this.restaurants
var results = queryString ? restaurants.filter(this.createFilter(queryString)) : restaurants
// 调用 callback 返回建议列表的数据
cb(results)
},
createFilter (queryString) {
return (restaurant) => {
return (restaurant.value.toLowerCase().indexOf(queryString.toLowerCase()) === 0)
}
},
loadAll () {
return [
{ 'value': 'vue' },
{ 'value': 'node.js' }
]
},
handleSelect (item) {
console.log(item)
},
submitArticle () {
this.$axios.post('/api/addArticle', {
data: this.article
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
}
},
mounted () {
this.restaurants = this.loadAll()
}
}
</script>
<style scoped>
.subBtn{
width: 100px;
margin: 0 auto;
}
</style>

View File

@@ -0,0 +1,133 @@
<template>
<div class="addArticle">
<el-form ref="article" :inline="true" :model="article" label-width="80px">
<el-form-item label="文章标题">
<el-input class="title" v-model="article.title"></el-input>
</el-form-item>
<el-form-item label="标签">
<el-autocomplete
class="inline-input"
v-model="article.sort"
:fetch-suggestions="querySearch"
placeholder="请输入内容"
@select="handleSelect"
></el-autocomplete>
</el-form-item>
<el-form-item label="是否置顶">
<el-switch v-model="article.top"></el-switch>
</el-form-item>
<el-form-item>
<el-button class="subBtn" type="primary" @click="submitArticle">发布</el-button>
<el-button class="subBtn" type="primary" @click="getContent">获取内容</el-button>
</el-form-item>
</el-form>
<div ref="editor" style="text-align:left"></div>
</div>
</template>
<script>
import E from 'wangeditor'
export default {
name: 'addArticle',
data() {
return {
article: {
title: '文章测试-标题',
sort: '',
top: true,
contentHtml: '',
},
initData: "",
restaurants: [],
}
},
methods: {
querySearch(queryString, cb) {
var restaurants = this.restaurants
var results = queryString ? restaurants.filter(this.createFilter(queryString)) : restaurants
// 调用 callback 返回建议列表的数据
cb(results)
},
createFilter(queryString) {
return (restaurant) => {
return (restaurant.value.toLowerCase().indexOf(queryString.toLowerCase()) === 0)
}
},
loadAll() {
return [
{'value': 'vue'},
{'value': 'node.js'}
]
},
handleSelect(item) {
console.log(item)
},
getContent: function () {
alert(this.article.contentHtml)
},
submitArticle() {
this.$axios.post('/article/addArticle', {
data: this.article
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
}
},
mounted() {
let that = this
this.restaurants = this.loadAll()
var editor = new E(this.$refs.editor)
editor.customConfig.onchange = (html) => {
that.article.contentHtml = html
}
editor.customConfig.uploadImgServer = '/editor/uploadImg' // 上传图片到服务器
editor.customConfig.uploadImgHooks = {
success: function (xhr, editor, result) {
// 图片上传并返回结果,图片插入成功之后触发
// xhr 是 XMLHttpRequst 对象editor 是编辑器对象result 是服务器端返回的结果
},
fail: function (xhr, editor, result) {
// 图片上传并返回结果,但图片插入错误时触发
// xhr 是 XMLHttpRequst 对象editor 是编辑器对象result 是服务器端返回的结果
},
error: function (xhr, editor) {
// 图片上传出错时触发
// xhr 是 XMLHttpRequst 对象editor 是编辑器对象
},
timeout: function (xhr, editor) {
// 图片上传超时时触发
// xhr 是 XMLHttpRequst 对象editor 是编辑器对象
},
}
editor.create()
}
}
</script>
<style scoped>
.title {
width: 1000px;
}
.subBtn {
width: 100px;
margin: 0 auto;
}
</style>
<style>
.el-autocomplete-suggestion {
z-index: 10010 !important;
}
.w-e-text-container {
height: 600px !important;
}
</style>

15
src/views/commerViews.vue Normal file
View File

@@ -0,0 +1,15 @@
<template>
<div>
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'commerViews'
}
</script>
<style scoped>
</style>

15
src/views/duoji/erji.vue Normal file
View File

@@ -0,0 +1,15 @@
<template>
<div>
无限级菜单测试======二级页面
</div>
</template>
<script>
export default {
name: 'erji'
}
</script>
<style scoped>
</style>

15
src/views/duoji/erji2.vue Normal file
View File

@@ -0,0 +1,15 @@
<template>
<div>
无限级菜单测试======二级2222页面
</div>
</template>
<script>
export default {
name: 'erji'
}
</script>
<style scoped>
</style>

15
src/views/duoji/sanji.vue Normal file
View File

@@ -0,0 +1,15 @@
<template>
<div>
无限级菜单测试======三级页面
</div>
</template>
<script>
export default {
name: 'sanji'
}
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,15 @@
<template>
<div>
无限级菜单测试======三级22222222页面
</div>
</template>
<script>
export default {
name: 'sanji1'
}
</script>
<style scoped>
</style>

15
src/views/duoji/siji.vue Normal file
View File

@@ -0,0 +1,15 @@
<template>
<div>
无限级菜单测试======四级页面
</div>
</template>
<script>
export default {
name: 'siji'
}
</script>
<style scoped>
</style>

15
src/views/duoji/wuji.vue Normal file
View File

@@ -0,0 +1,15 @@
<template>
<div>
无限级菜单测试======五级页面
</div>
</template>
<script>
export default {
name: 'wuji'
}
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,28 @@
<template>
<div>
<markdown :onchange="change" :initData="initData"></markdown>
</div>
</template>
<script>
import Markdown from '../../components/markdown/markdown-editor'
import initData from '../../markData.js'
export default {
name: 'markdownView',
data () {
return {
initData: initData,
}
},
components: {Markdown},
methods: {
change () {
console.log(arguments)
}
}
}
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,30 @@
<template>
<div>
<div ref="editor" style="text-align:left"></div>
<button v-on:click="getContent">查看内容</button>
</div>
</template>
<script>
import E from 'wangeditor'
export default {
name: "wangeditor",
methods: {
getContent: function () {
alert(this.editorContent)
}
},
mounted() {
var editor = new E(this.$refs.editor)
editor.customConfig.onchange = (html) => {
this.editorContent = html
}
editor.create()
}
}
</script>
<style scoped>
</style>

126
src/views/icon/index.vue Normal file
View File

@@ -0,0 +1,126 @@
<template>
<div>
<h3>框架内置了element ui和Font Awesome两种图标库</h3>
<p class="text"><span class="name">element ui图标</span>使用方法直接通过设置类名为 el-icon-iconName 来使用即可例如<span class="code">&lt;i class="el-icon-edit"&gt;&lt;/i&gt;</span></p>
<ul class="ele-icoo">
<li>
<span>
<i class="el-icon-download"></i>
<span class="iconame">el-icon-download</span>
</span>
</li>
<li>
<span>
<i class="el-icon-loading"></i>
<span class="iconame">el-icon-loading</span>
</span>
</li>
<li>
<span>
<i class="el-icon-setting"></i>
<span class="iconame">el-icon-setting</span>
</span>
</li>
<li>
<span>
<a target="_blank" href="http://element-cn.eleme.io/#/zh-CN/component/icon">更多element ui图标</a>
</span>
</li>
</ul>
<div style="clear: both"></div>
<p class="text"><span class="name">Font Awesome图标</span>本框架已经内置该图标库675个图标,不需要另外引入安装,可以直接使用,使用方法直接通过设置类名为 'fa fa-iconName' 来使用即可例如<span class="code">&lt;i class="fa fa-camera-retro"&gt;&lt;/i&gt;</span>
<p class="text">使用 fa-lg (33%递增)fa-2x fa-3xfa-4x或者 fa-5x 来放大图标,例如<span class="code">&lt;i class="fa fa-camera-retro fa-2x"&gt;&lt;/i&gt;</span></p>
<p class="text">更多功能及用法点击 <a target="_blank" href="http://fontawesome.dashgame.com/#basic"><strong>此处</strong></a> </p>
<div>
<ul class="ele-icoo">
<li>
<span>
<i class="fa fa-power-off"></i>
<span class="iconame">power-off</span>
</span>
</li>
<li>
<span>
<i class="fa fa-server"></i>
<span class="iconame">server</span>
</span>
</li>
<li>
<span>
<i class="fa fa-tags"></i>
<span class="iconame">tags</span>
</span>
</li>
<li>
<span>
<a target="_blank" href="http://fontawesome.dashgame.com/">更多Font Awesome图标</a>
</span>
</li>
</ul>
</div>
</div>
</template>
<script>
export default {
name: 'index'
}
</script>
<style lang="scss">
.name{
font-size: 26px;
color: #666666;
display: block;
margin-bottom: 10px;
margin-top: 24px;
}
.code{
background-color: #e5e8ec;
padding: 0 4px;
border: 1px solid #ced1dc;
border-radius: 4px;
}
.text{
font-size: 14px;
color: #5e6d82;
line-height: 1.5em;
margin: 5px 0px;
}
.ele-icoo{
max-width: 100%;
li{
float: left;
width: 12.5%;
text-align: center;
height: 120px;
line-height: 120px;
color: #666;
font-size: 13px;
transition: color .15s linear;
border-right: 1px solid #eee;
border-bottom: 1px solid #eee;
margin-right: -1px;
margin-bottom: -1px;
span{
display: inline-block;
line-height: normal;
vertical-align: middle;
font-family: Helvetica Neue,Helvetica,PingFang SC,Hiragino Sans GB,Microsoft YaHei,SimSun,sans-serif;
color: #99a9bf;
i{
display: block;
font-size: 32px;
margin-bottom: 15px;
color: #606266;
code{
display: inline-block;
padding: 0 3px;
height: 1em;
color: #606266;
}
}
}
}
}
</style>

View File

@@ -0,0 +1,237 @@
<template>
<div>
<el-row :gutter="20">
<el-col :span="8">
<div class="card kjfs">
<p class="title"><i class="fa fa-th-large fa-lg"></i>快捷方式</p>
<ul>
<li><router-link to="/addArticle" class="kjfs kjfs-bluee"><span><i class="el-icon-tickets fa-2x"></i></span><span>发表文章</span></router-link></li>
<li><router-link to="/dragTabe" class="kjfs kjfs-pinkk"><span><i class="fa fa-hand-stop-o fa-2x"></i></span><span>拖拽排序</span></router-link></li>
<li><router-link to="/pagePermissions" class="kjfs kjfs-yelloww"><span><i class="fa fa-universal-access fa-2x"></i></span><span>权限测试</span></router-link></li>
</ul>
<ul>
<li><router-link to="/upload" class="kjfs kjfs-grennn"><span><i class="fa fa-cloud-upload fa-2x"></i></span><span>文件上传</span></router-link></li>
<li><router-link to="/navClassifies" class="kjfs kjfs-purplee"><span><i class="fa el-icon-menu fa-2x"></i></span><span>前台菜单</span></router-link></li>
<li><router-link to="/markdown" class="kjfs kjfs-lightBluee"><span><i class="fa fa-file-code-o fa-2x"></i></span><span>编辑器</span></router-link></li>
</ul>
</div>
</el-col>
<el-col :span="8">
<div class="card dbsx">
<p class="title"><i class="fa fa-file-text-o"></i>待办事项</p>
<ul>
<li><router-link to="#"><span>待审评论</span><span class="num">66</span></router-link></li>
<li><router-link to="#"><span>待审帖子</span><span class="num">66</span></router-link></li>
</ul>
<ul>
<li><router-link to="#"><span>待审商品</span><span class="num">66</span></router-link></li>
<li><router-link to="#"><span>代发货</span><span class="num">66</span></router-link></li>
</ul>
</div>
</el-col>
<el-col :span="8">
<div class="card bbxx">
<p class="title"><i class="fa fa-server"></i>版本信息</p>
<div class="table">
<p><span class="tit">当前版本</span>v1.0.0</p>
<p><span class="tit">基于框架</span>vue2.0全家桶 + element-ui</p>
<p><span class="tit">主要特色</span>单页面 / 响应式 / 无限级菜单 / 权限管理 / 极简</p>
<p><span class="tit">获取渠道</span>
<span class="gitbox">
<a target="_blank" href="https://github.com/Nirongxu/vue-xuAdmin.git"><el-button type="primary" icon="el-icon-download" size="small">github</el-button></a>
<a target="_blank" href="https://gitee.com/nirongxu/xu-webplatform.git"><el-button type="primary" icon="el-icon-download" size="small">码云</el-button></a>
</span>
</p>
</div>
</div>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<line-echarts id="lineEcharts" height="300px" ref="echarts"></line-echarts>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<maintable id="maintable"></maintable>
</el-col>
</el-row>
</div>
</template>
<script>
import LineEcharts from '../../components/ECharts/lineEcharts'
import Maintable from '../table/maintable'
export default {
name: 'mainIndex',
components: {Maintable, LineEcharts},
mounted () {
this.selfAdaption()
},
methods: {
// echart自适应
selfAdaption () {
let that = this
setTimeout(() => {
window.onresize = function () {
if (that.$refs.echarts) {
that.$refs.echarts.chart.resize()
}
}
}, 10)
}
}
}
</script>
<style lang="scss">
$top:top;
$bottom:bottom;
$left:left;
$right:right;
$leftright: ($left, $right);
$pinkk: #eec2d3;
$bluee: #409eff;
$yelloww: #f4d884;
$grennn: #89dda0;
$purplee: #78a2ea;
$lightBluee: #b8d6ff;
$list: bluee pinkk yelloww grennn purplee lightBluee;
$list1: $bluee $pinkk $yelloww $grennn $purplee $lightBluee;
%shadow{
background: #fff;
-webkit-box-shadow: 4px 4px 40px rgba(0, 0, 0, 0.2);
box-shadow: 4px 4px 40px rgba(0, 0, 0, 0.2);
border-color: rgba(0, 0, 0, 0.2);
.title{
font-size: 14px;
padding: 10px;
i{
margin-#{$right}: 5px;
}
}
}
@mixin flex($direction:row,$content:space-between){
display: flex;
flex-direction: $direction;
justify-content: $content;
}
.card{
color: #666;
@extend %shadow;
ul{
@include flex;
li{
flex: 1;
a{
color: #666666;
align-items:center;
padding-#{$top}: 20px;
padding-#{$bottom}: 20px;
@include flex(column);
span{
height: 44px;
}
.num{
line-height: 44px;
font-size: 42px;
color: $bluee;
margin: 0px;
}
}
.kjfs-bluee{
color: $bluee;
}
.kjfs-pinkk{
color: $pinkk;
}
.kjfs-yelloww{
color: $yelloww;
}
.kjfs-grennn{
color: $grennn;
}
.kjfs-purplee{
color: $purplee;
}
.kjfs-lightBluee{
color: $lightBluee;
}
&:hover{
.kjfs-bluee{
color: #ffffff;
background: $bluee;
}
.kjfs-pinkk{
color: #ffffff;
background: $pinkk;
}
.kjfs-yelloww{
color: #ffffff;
background: $yelloww;
}
.kjfs-grennn{
color: #ffffff;
background: $grennn;
}
.kjfs-purplee{
color: #ffffff;
background: $purplee;
}
.kjfs-lightBluee{
color: #ffffff;
background: $lightBluee;
}
}
}
}
.table{
padding: 21px;
p{
height: 52px;
line-height: 52px;
border: 1px solid #cccccc;
overflow: hidden;
border-#{$top}: none;
@include flex( null,start);
&:first-child{
border-#{$top}: 1px solid #cccccc;
}
span{
}
.tit{
width: 90px;
min-width: 90px;
height: 100%;
text-align: center;
border-#{$right}: 1px solid #cccccc;
margin-#{$right}: 18px;
}
span.gitbox{
flex: 1;
height: 100%;
overflow: hidden;
@include flex(row,start);
a{
&:first-child{
margin-#{$right}: 30px;
}
}
}
}
}
}
#lineEcharts{
margin-#{$top}: 30px;
padding-#{$top}: 30px;
@extend %shadow;
}
#maintable{
margin-#{$top}: 30px;
padding-#{$top}: 10px;
@extend %shadow;
}
</style>

View File

@@ -0,0 +1,21 @@
<template>
<div>
<p>Copyright © 2018 xuAdmin.</p>
</div>
</template>
<script>
export default {
name: 'bottom'
}
</script>
<style scoped>
p{
height: 60px;
line-height: 60px;
text-align: left;
font-size: 12px;
color: #999999;
}
</style>

View File

@@ -0,0 +1,157 @@
<template>
<div>
<el-aside id="asideNav">
<div class="logo-name">
<p v-if="$store.getters.logoShow">XU</p>
<p v-else>vue-xuAdmin后台模板</p>
</div>
<el-menu :default-active="$route.path" class="el-menu-vertical"
@select="selectmenu"
:collapse="$store.getters.isCollapse"
background-color="#03152A"
text-color="rgba(255,255,255,.7)"
active-text-color="#ffffff"
:router="$store.getters.uniquerouter"
:unique-opened="$store.getters.uniquerouter"
:collapse-transition="true"
>
<template v-for="(item,index) in $store.getters.routers" v-if="!item.hidden">
<el-submenu v-if="!item.alone && item.children.length>0" :index="index+''">
<template slot="title">
<i :class="item.iconCls?item.iconCls:[fa,fa-server]"></i>
<span slot="title">{{ $t(`routeNmae.${item.name}`) }}</span>
</template>
<menu-tree :menuData="item.children"></menu-tree>
</el-submenu>
<el-menu-item :index="item.path" v-else>
<i :class="item.iconCls?item.iconCls:[fa,fa-file]"></i>
<span slot="title">{{ $t(`routeNmae.${item.name}`) }}</span>
</el-menu-item>
</template>
</el-menu>
</el-aside>
</div>
</template>
<script>
import menuTree from './menuTree'
export default {
name: 'asideNav',
components: {
menuTree,
},
watch: {
// 监听浏览器直接输入路由将此路由添加到tabnavBox
'$route.path': function (val) {
this.selectmenu(val)
}
},
methods: {
selectmenu (key) {
let router = this.$store.getters.routers
let name = ''
let navTitle = function (path, routerARR) {
for (let i = 0; i < routerARR.length; i++) {
if (routerARR[i].children.length > 0 || routerARR[i].path === path) {
if (routerARR[i].path === path && routerARR[i].children.length < 1) {
name = routerARR[i].name
break
}
navTitle(path, routerARR[i].children)
}
}
return name
}
this.$store.dispatch('addTab', {
title: navTitle(key, router),
path: key
})
}
}
}
</script>
<style lang="scss">
$top: top;
$bottom: bottom;
$left: left;
$right: right;
%w100 {
width: 100%;
}
%h100 {
height: 100%;
}
%cursor {
cursor: pointer;
}
@mixin set-value($side, $value) {
@each $prop in $leftright {
#{$side}-#{$prop}: $value;
}
}
#asideNav {
width: auto !important;
display: flex;
flex-direction: column;
border-right: solid 1px #e6e6e6;
.logo-name {
background-color: #03152A !important;
@extend %w100;
font-weight: 300;
z-index: 999;
p {
height: 50px;
line-height: 50px;
text-align: center;
font-size: 16px;
color: #5e6d82;
}
}
.el-menu-vertical:not(.el-menu--collapse) {
width: 200px;
@extend %h100;
overflow-y: scroll;
}
.el-menu {
flex: 1;
overflow: inherit;
border-right: none;
&::-webkit-scrollbar {
display: none;
}
.fa {
vertical-align: middle;
margin-right: 5px;
width: 24px;
text-align: center;
font-size: 18px;
}
.el-menu-item {
background-color: #020f1d !important;
border-bottom: 1px solid #020f1d;
&:hover {
color: #ffffff !important;
background-color: #375573 !important;
}
}
.el-menu-item.is-active {
background-color: #56a9ff !important
}
.is-opened > .el-submenu__title > .el-icon-arrow-down {
color: #ffffff;
font-weight: 500;
font-size: 18px;
}
}
}
</style>

View File

@@ -0,0 +1,29 @@
<template>
<div>
<template v-for="(child,index) in menuData">
<el-submenu v-if="child.children.length > 0" :index="child.path">
<template slot="title">
<i :class="child.iconCls?child.iconCls:[fa,fa-file]"></i>
<span slot="title">{{ $t(`routeNmae.${child.name}`) }}</span>
</template>
<menu-tree :menuData="child.children"></menu-tree>
</el-submenu>
<el-menu-item v-else :index="child.path">
<i :class="child.iconCls?child.iconCls:[fa,fa-file]"></i>
<span slot="title">{{ $t(`routeNmae.${child.name}`) }}</span>
</el-menu-item>
</template>
</div>
</template>
<script>
export default {
name: 'menuTree',
props: ['menuData']
}
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,148 @@
<template>
<div>
<el-header id="header">
<span class="hideAside" @click="collapse"><i class="fa fa-indent fa-lg"></i></span>
<ul class="personal">
<li class="fullScreen" @click="fullScreen">
<el-tooltip class="item" effect="dark" content="全屏" placement="bottom"><i
class="fa fa-arrows-alt fa-lg"></i></el-tooltip>
</li>
<li>
<langSelect></langSelect>
</li>
<li>{{ $t(`role.${this.$store.getters.info.role}`) }}</li>
<li>
<el-dropdown @command="handleCommand">
<span class="el-dropdown-link">
夏洛克丶旭<i class="el-icon-arrow-down el-icon--right"></i>
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="a">{{ $t('userDropdownMenu.basicInfor') }}</el-dropdown-item>
<el-dropdown-item command="b">{{ $t('userDropdownMenu.changePassword') }}</el-dropdown-item>
<el-dropdown-item command="logout" divided>{{ $t('userDropdownMenu.logout') }}</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</li>
<li class="icon"><img :src="avatar"/></li>
</ul>
</el-header>
<tabNav></tabNav>
</div>
</template>
<script>
import Cookies from 'js-cookie'
import langSelect from '../../../components/lang/langSelect'
import tabNav from './tabNav'
export default {
name: 'Header',
components: {tabNav, langSelect},
data () {
return {
isfullScreen: true,
avatar: './static/images/icon.jpg'
}
},
methods: {
collapse () {
this.$store.dispatch('collapse')
},
fullScreen () {
if (this.isfullScreen) {
var docElm = document.documentElement
if (docElm.requestFullscreen) {
docElm.requestFullscreen()
} else if (docElm.mozRequestFullScreen) {
docElm.mozRequestFullScreen()
} else if (docElm.webkitRequestFullScreen) {
docElm.webkitRequestFullScreen()
} else if (elem.msRequestFullscreen) {
elem.msRequestFullscreen()
}
this.isfullScreen = false
} else {
if (document.exitFullscreen) {
document.exitFullscreen()
} else if (document.mozCancelFullScreen) {
document.mozCancelFullScreen()
} else if (document.webkitCancelFullScreen) {
document.webkitCancelFullScreen()
} else if (document.msExitFullscreen) {
document.msExitFullscreen()
}
this.isfullScreen = true
}
},
handleCommand (command) {
if (command === 'logout') {
Cookies.remove('token');
location.reload()
}
}
}
}
</script>
<style lang="scss">
$top: top;
$bottom: bottom;
$left: left;
$right: right;
$leftright: ($left, $right);
%w100 {
width: 100%;
}
%h100 {
height: 100%;
}
%cursor {
cursor: pointer;
}
html, body, #app, .el-container, #asideNav, ul.el-menu {
@extend %h100;
}
@mixin set-value($side, $value) {
@each $prop in $leftright {
#{$side}-#{$prop}: $value;
}
}
#header {
max-height: 50px;
line-height: 50px;
box-shadow: 0 1px 2px 0 rgba(0, 0, 0, .05);
display: flex;
justify-content: space-between;
.hideAside {
@extend %cursor;
}
.personal {
display: flex;
flex-direction: row;
li {
@include set-value(margin, 13px);
font-size: 12px;
}
.fullScreen {
@extend %cursor;
}
.el-dropdown-link {
@extend %cursor;
}
.icon img {
margin-#{$top}: 7px;
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
border-radius: 5px;
width: 40px;
height: 40px;
}
}
}
</style>

View File

@@ -0,0 +1,192 @@
<template>
<div>
<div class="tabnavBox">
<transition-group name="list" tag="ul">
<li v-for="(item, index) in $store.getters.tabnavBox" @contextmenu.prevent="openMenu(item,$event,index)"
:key="item.title" class="tabnav" :class="{ active: $route.path === item.path }">
<router-link :to="item.path">{{ $t(`routeNmae.${item.title}`) }}</router-link>
<i @click="removeTab(item)" class="el-icon-error" v-if="index !== 0"></i>
</li>
</transition-group>
</div>
<ul v-show="this.rightMenuShow" :style="{left:this.left+'px',top:this.top+'px'}" class="menuBox">
<li @click="removeTab($store.getters.rightNav)"><i class="fa fa-remove"></i>{{ $t('rightMenu.close') }}</li>
<li @click="removeOtherTab($store.getters.rightNav)">{{ $t('rightMenu.closeOther') }}</li>
<li @click="removeAllTab">{{ $t('rightMenu.closeAll') }}</li>
</ul>
</div>
</template>
<script>
export default {
name: 'tabNav',
data () {
return {
rightMenuShow: false,
left: 0,
top: 0
}
},
methods: {
openMenu (item, e, index) {
if (index === 0) {
return false
}
this.rightMenuShow = true
this.left = e.clientX + 10
this.top = e.clientY
this.$store.dispatch('openMenu', item)
},
removeTab (tabItem) {
this.$store.dispatch('removeTab', {tabItem, fullPath: this.$route.fullPath, router: this.$router})
},
removeOtherTab (tabItem) {
this.$store.dispatch('removeOtherTab', {tabItem, router: this.$router})
},
removeAllTab () {
this.$store.dispatch('removeOtherTab', {all: true, router: this.$router})
}
},
watch: {
rightMenuShow (value) {
if (value) {
document.body.addEventListener('click', () => {
this.rightMenuShow = false
})
} else {
document.body.removeEventListener('click', () => {
this.rightMenuShow = false
})
}
}
}
}
</script>
<style>
.tabnav {
display: inline-block;
transition: all 0.5s;
}
.list-enter, .list-leave-to
/* .list-leave-active for below version 2.1.8 */
{
opacity: 0;
transform: translateY(30px);
}
.list-enter-active {
transition: all 0.5s;
}
.list-leave-active {
position: absolute;
transition: all 1s;
}
</style>
<style lang="scss">
$top: top;
$bottom: bottom;
$left: left;
$right: right;
$leftright: ($left, $right);
%w100 {
width: 100%;
}
%h100 {
height: 100%;
}
%cursor {
cursor: pointer;
}
@mixin set-value($side, $value) {
@each $prop in $leftright {
#{$side}-#{$prop}: $value;
}
}
.tabnavBox {
@extend %w100;
height: 42px;
min-height: 42px;
overflow: hidden;
border-#{$top}: 1px solid #f6f6f6;
border-#{$bottom}: 1px solid #d8dce5;
-webkit-box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 0 3px 0 rgba(0, 0, 0, 0.04);
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 0 3px 0 rgba(0, 0, 0, 0.04);
ul {
display: flex;
justify-content: flex-start;
padding-#{$left}: 20px;
flex-wrap: nowrap;
overflow-x: auto;
li {
height: 30px;
line-height: 31px;
@extend %cursor;
margin-#{$top}: 6px;
margin-#{$right}: 5px;
border: 1px solid #cccccc;
overflow: hidden;
&:not(:first-child) {
padding-#{$right}: 10px;
min-width: 80px;
}
a {
@include set-value(padding, 13px);
display: inline-block;
@extend %h100;
font-size: 12px;
color: #999999;
}
&:nth-child(n+2) {
a {
padding-#{$right}: 15px;
}
}
i {
@extend %cursor;
&:hover {
color: red;
}
}
}
li.active {
background: #409eff;
color: #ffffff;
a {
color: #ffffff;
}
}
}
}
.menuBox {
margin: 0;
background: #fff;
z-index: 999;
position: absolute;
padding: 5px 0;
border: 1px solid #cccccc;
font-size: 12px;
font-weight: 400;
color: #333;
box-shadow: 2px 1px 6px 0 rgba(0, 0, 0, .3);
li {
margin: 0;
padding: 7px 16px;
@extend %cursor;
&:hover {
background: #e1e6ea;
}
}
}
</style>

106
src/views/layout/layout.vue Normal file
View File

@@ -0,0 +1,106 @@
<template>
<div id="loyout">
<el-container>
<layoutAside></layoutAside>
<el-container>
<layoutHeader></layoutHeader>
<el-main id="elmain">
<transition name="main" mode="out-in">
<router-view></router-view>
</transition>
</el-main>
<el-footer>
<Bottom></Bottom>
</el-footer>
</el-container>
</el-container>
</div>
</template>
<script>
import layoutAside from './aside/aside'
import layoutHeader from './header/header'
import Bottom from './Footer/bottom'
import langSelect from '../../components/lang/langSelect'
export default {
name: 'dc-home',
components: {
layoutHeader,
Bottom,
langSelect,
layoutAside
},
created () {
this.$router.push('/index')
}
}
</script>
<style>
.main-enter, .main-leave-to {
opacity: 0;
transform: translateY(30px);
}
.main-enter-active {
transition: all 0.2s;
}
.main-leave-active {
position: absolute;
transition: all 0.3s;
}
</style>
<style lang="scss">
* {
margin: 0px;
padding: 0px;
}
body {
background-color: #f2f2f2;
font-size: 14px;
color: #333333;
}
li {
list-style: none;
}
a {
text-decoration: none;
}
$top: top;
$bottom: bottom;
$left: left;
$right: right;
$leftright: ($left, $right);
%w100 {
width: 100%;
}
%h100 {
height: 100%;
}
%cursor {
cursor: pointer;
}
html, body, #loyout, .el-container, #asideNav, ul.el-menu {
@extend %h100;
}
@mixin set-value($side, $value) {
@each $prop in $leftright {
#{$side}-#{$prop}: $value;
}
}
#elmain {
background-color: #f0f2f5;
}
</style>

259
src/views/login/index.vue Normal file
View File

@@ -0,0 +1,259 @@
<template>
<div id="login">
<div class="loginConbox">
<div class="header">
<!--<div class="logo">-->
<!--<img src="../../assets/logo.png">-->
<!--</div>-->
</div>
<div class="loginBox">
<div class="loginCon">
<p class="title">vue-xuadmin权限管理后台模板</p>
<p class="title">前台: vue + element-ui</p>
<el-card shadow="always" class="login-module" v-if="smdl">
<div slot="header" class="clearfix formTitlt">
<span>密码登录</span>
<span class="titIconbox">
<i class="iconfont xu-saomadenglu2 fa-lg iconcolor"></i>
<i class="iconfont xu-saomadenglu01 el-icon--right fa-lg pointer" @click="smdl = !smdl"></i>
</span>
</div>
<el-form :model="loginForm" status-icon label-width="100px" class="demo-ruleForm">
<el-form-item>
<el-input type="text" v-model="loginForm.username" auto-complete="off" placeholder="请输入登录账号"></el-input>
</el-form-item>
<el-form-item>
<el-input type="password" v-model="loginForm.password" auto-complete="off"
placeholder="请输入登录密码"></el-input>
</el-form-item>
<el-form-item>
<el-button class="subBtn" type="primary" @click="submitForm">登录</el-button>
</el-form-item>
<p class="smalltxt">
<router-link class="a" to="#">忘记密码</router-link>
<router-link class="a" to="#">忘记会员名</router-link>
<router-link class="a" to="#">免费注册</router-link>
</p>
</el-form>
</el-card>
<el-card shadow="always" class="login-module" v-else>
<div slot="header" class="clearfix formTitlt">
<span>扫码登录</span>
<span class="titIconbox">
<i class="iconfont xu-mimadenglu1 fa-lg iconcolor"></i>
<i class="iconfont xu-imagevector el-icon--right fa-lg pointer" @click="smdl = !smdl"></i>
</span>
</div>
<div class="ewmbox">
<div class="ewm">
<img src="https://img.alicdn.com/tfscom/TB1ivYYyHvpK1RjSZFqwu3XUVXa.png">
</div>
<div class="ewmicon">
<i class="iconfont xu-saomadenglu fa-2x iconcolor"></i>
<p>打开 微信 扫一扫登录</p>
</div>
<p class="smalltxt">
<router-link class="a" to="#">免费注册</router-link>
</p>
</div>
</el-card>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
data () {
return {
smdl: true,
loginForm: {
username: 'vue-xuadmin',
password: '123456'
}
}
},
methods: {
submitForm () {
let that = this
if (this.loginForm.username === '' || this.loginForm.password === '') {
this.$message({
showClose: true,
message: '账号或密码不能为空',
type: 'error'
})
return false
} else {
// 将 username 设置为 token 存储在 store仅为测试效果实际存储 token 以后台返回为准
that.$store.dispatch('setToken', that.loginForm.username).then(() => {
that.$router.push({path: '/'})
}).catch(res => {
that.$message({
showClose: true,
message: res,
type: 'error'
})
})
}
},
message() {
const h = this.$createElement;
this.$notify({
title: '账号密码',
message: h('i', { style: 'color: teal'}, '账号密码可以随意填写,为了测试效果填写的账号将会被存储为临时假 token'),
duration: 6000
});
},
},
mounted() {
this.message()
}
}
</script>
<style lang="scss">
#login {
width: 100%;
height: 100%;
background-color: #2d3a4b;
.loginConbox{
background: #2d3a4b;
}
.header {
height: 60px;
position: relative;
background: #2d3a4b;
/*border-bottom: 1px solid rgba(255, 255, 255, 0.3);*/
.logo{
margin-left: 30px;
width: 500px;
float: left;
height: 40px;
padding-top: 10px;
img{
height: 100%;
}
}
}
.loginBox {
.iconcolor {
color: #409EFF;
}
padding: 74px 0 118px;
.loginCon {
width: 990px;
margin: auto;
position: relative;
height: 388px;
.el-card__header {
border-bottom: 0px;
}
.title{
font-size: 36px;
font-weight: 600;
color: #ffffff;
width: 500px;
float: left;
margin-top: 0px;
&:first-child{
font-size: 34px;
margin-top: 50px;
margin-bottom: 30px;
}
}
.login-module {
width: 380px;
height: 325px;
margin-top: 60px;
border: none;
position: absolute;
right: 0;
.formTitlt {
font-size: 18px;
font-weight: 400;
.titIconbox {
float: right;
.pointer {
cursor: pointer;
}
}
}
.smalltxt {
text-align: right;
.a {
text-decoration: none;
color: #999999;
font-size: 12px;
margin-left: 8px;
}
}
}
.el-form-item__content {
margin-left: 0px !important;
.subBtn {
width: 100%;
}
}
}
.el-input__inner, .el-button, .el-card, .el-message {
border-radius: 0px !important;
}
.el-form-item__content .ico {
position: absolute;
top: 0px;
left: 0px;
z-index: 999;
width: 40px;
height: 39px;
text-align: center;
border-right: 1px solid #ccc;
}
.ewmbox {
width: 100%;
height: 240px;
margin-top: -25px;
.ewm {
width: 140px;
height: 140px;
margin: 20px auto;
p {
font-size: 12px;
padding-left: 40px;
margin: 0;
}
}
.ewmicon {
width: 140px;
margin: 20px auto 0;
.iconfont {
float: left;
}
p {
font-size: 12px;
padding-left: 40px;
margin: 0;
}
}
}
}
}
</style>

View File

@@ -0,0 +1,22 @@
<template>
<div style="margin-top: 50px">
<h3>下面按钮根据当前用户的权限来显示隐藏</h3>
<p>当前用户角色 "{{$store.getters.info.permissions}}"</p>
<p>没权限按钮<el-button type="primary" plain size="medium">查看</el-button></p>
<p>需要 ["管理员"]<el-button type="primary" plain size="medium" v-role-btn="['admin']">添加</el-button></p>
<p>需要 ["超级管理员"]<el-button type="danger" plain size="medium" v-role-btn="['superAdmin']">删除</el-button></p>
<p>需要 ["超级管理员", "管理员"]<el-button type="primary" plain size="medium" v-role-btn="['superAdmin','admin']">修改</el-button></p>
</div>
</template>
<script>
export default {
name: 'btnPermissions'
}
</script>
<style scoped>
p{
margin: 20px 0px;
}
</style>

View File

@@ -0,0 +1,68 @@
<template>
<div>
<el-radio v-model="permissions" label="superAdmin" border>超级管理员</el-radio>
<el-radio v-model="permissions" label="admin" border>管理员</el-radio>
<el-radio v-model="permissions" label="ordinary" border>普通用户</el-radio>
<div style="margin: 50px 0px;">
[权限: "{{options.permissions}}", 角色: "{{options.role}}"]
</div>
<h3>需要权限的目录</h3>
<p>上传["超级管理员"]</p>
<p>编辑器["超级管理员", 管理员]</p>
<p>系统设置["超级管理员"]</p>
</div>
</template>
<script>
export default {
name: 'pagePermissions',
data () {
return {
permissions: this.$store.getters.info.role,
options: {
role: this.$store.getters.info.role,
permissions: this.$store.getters.info.permissions,
}
};
},
mounted (){
this.$store.dispatch('setRole', this.options)
},
watch: {
permissions (newQuestion, oldQuestion) {
switch (newQuestion) {
case 'superAdmin':
this.options = {
role: 'superAdmin',
permissions: '超级管理员'
}
break
case 'admin':
this.options = {
role: 'admin',
permissions: '管理员'
}
break
case 'ordinary':
this.options = {
role: 'ordinary',
permissions: '普通用户'
}
}
this.$store.dispatch('setRole', this.options)
// 刷新 tabnav 权限管理测试需要
this.$store.dispatch('removeOtherTab', {tabItem: {
title: 'pageControl',
path: '/pagePermissions'
}, router: this.$router})
}
}
}
</script>
<style scoped>
p{
margin: 20px 0px;
}
</style>

View File

@@ -0,0 +1,136 @@
<template>
<div class="wrap">
<el-form :model="dynamicValidateForm" ref="dynamicValidateForm" label-width="100px" class="demo-dynamic">
<el-form-item
prop="indexName"
label="首页"
:rules="{
required: true, message: '分类不能为空', trigger: 'blur'
}"
>
<el-input placeholder="导航名称" v-model="dynamicValidateForm.indexName"></el-input>
<el-input placeholder="path路径" disabled v-model="dynamicValidateForm.indexHref"></el-input>
</el-form-item>
<el-form-item
v-for="(domain, index) in dynamicValidateForm.domains"
:label="'导航' + (index+1)"
:key="domain.key"
:prop="'domains.' + index + '.value'"
>
<el-input placeholder="导航名称" v-model="domain.name"></el-input>
<el-input placeholder="path路径" v-model="domain.href"></el-input>
<el-button @click.prevent="removeDomain(domain)">删除</el-button>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm('dynamicValidateForm')">提交</el-button>
<el-button @click="addDomain">新增分类</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
export default {
name: 'navClassify',
data () {
return {
dynamicValidateForm: {
domains: [],
indexName: '首页',
indexHref: '/index'
}
}
},
methods: {
submitForm (formName) {
let oneData = {
name: this.dynamicValidateForm.indexName,
href: this.dynamicValidateForm.indexHref
}
function coppyArray (arr) {
return arr.map((e) => {
if (typeof e === 'object') {
return Object.assign({}, e)
} else {
return e
}
})
}
let arrdata = coppyArray(this.dynamicValidateForm.domains)
arrdata.unshift(oneData)
let formData = arrdata
let that = this
this.$refs[formName].validate((valid) => {
if (valid) {
this.$axios.post('/api/setting/setNavClassify', {
navClassifyData: formData
})
.then(response => {
console.log(response)
that.$message({
showClose: true,
message: response.data.msg,
type: 'success'
})
})
.catch(err => {
console.log(err)
that.$message({
showClose: true,
message: err,
type: 'error'
})
})
} else {
console.log('error submit!!')
return false
}
})
},
resetForm (formName) {
this.$refs[formName].resetFields()
},
removeDomain (item) {
var index = this.dynamicValidateForm.domains.indexOf(item)
if (index !== -1) {
this.dynamicValidateForm.domains.splice(index, 1)
}
},
addDomain () {
this.dynamicValidateForm.domains.push({
indexName: '',
indexHref: '',
key: Date.now()
})
}
},
mounted () {
// 页面加载完之后从后台获取导航列表
let that = this
// this.$axios.get('/api/setting/getNavClassify')
// .then(function (response) {
// if (response.status === 200) {
// console.log(response)
// that.dynamicValidateForm.indexName = response.data.navList[0].name
// that.dynamicValidateForm.indexHref = response.data.navList[0].href
// response.data.navList.splice(0, 1)
// that.dynamicValidateForm.domains = that.dynamicValidateForm.domains.concat(response.data.navList)
// console.log(that.dynamicValidateForm)
// return false
// }
// })
// .catch(function (error) {
// console.log(error)
// })
}
}
</script>
<style scoped>
.el-input {
margin-right: 10px;
width: 270px;
vertical-align: top;
}
</style>

View File

@@ -0,0 +1,106 @@
<template>
<div>
<h3>多选</h3>
<p>选择多行数据时使用 Checkbox</p>
<template>
<el-table
ref="multipleTable"
:data="tableData4"
tooltip-effect="dark"
style="width: 100%"
@selection-change="handleSelectionChange">
<el-table-column
type="selection"
width="55">
</el-table-column>
<el-table-column
label="日期"
width="120">
<template slot-scope="scope">{{ scope.row.date }}</template>
</el-table-column>
<el-table-column
prop="name"
label="姓名"
width="120">
</el-table-column>
<el-table-column
prop="address"
label="地址"
show-overflow-tooltip>
</el-table-column>
</el-table>
<div style="margin-top: 20px">
<el-button @click="toggleSelection([tableData4[1], tableData4[2]])">切换第二第三行的选中状态</el-button>
<el-button @click="toggleSelection()">取消选择</el-button>
</div>
</template>
</div>
</template>
<script>
export default {
name: 'dataTables',
data () {
return {
tableData4: [{
date: '2016-05-03',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄'
}, {
date: '2016-05-02',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄'
}, {
date: '2016-05-04',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄'
}, {
date: '2016-05-01',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄'
}, {
date: '2016-05-08',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄'
}, {
date: '2016-05-06',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄'
}, {
date: '2016-05-07',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄'
}],
multipleSelection: []
}
},
methods: {
toggleSelection (rows) {
if (rows) {
rows.forEach(row => {
this.$refs.multipleTable.toggleRowSelection(row);
});
} else {
this.$refs.multipleTable.clearSelection();
}
},
handleSelectionChange (val) {
this.multipleSelection = val;
}
}
}
</script>
<style scoped>
h3{
margin: 25px 0 20px;
font-weight: 400;
color: #1f2f3d;
font-size: 22px;
}
p{
font-size: 14px;
color: #5e6d82;
line-height: 1.5em;
}
</style>

View File

@@ -0,0 +1,141 @@
<template>
<div>
<template>
<el-table
:data="tableData"
style="width: 100%;padding-bottom: 3px">
<el-table-column
type="index">
</el-table-column>
<el-table-column
prop="date"
label="日期"
width="180">
</el-table-column>
<el-table-column
label="姓名"
width="180">
<template slot-scope="scope">
<el-popover trigger="hover" placement="top">
<p>姓名: {{ scope.row.name }}</p>
<p>住址: {{ scope.row.address }}</p>
<div slot="reference" class="name-wrapper">
<el-tag size="medium">{{ scope.row.name }}</el-tag>
</div>
</el-popover>
</template>
</el-table-column>
<el-table-column
prop="address"
label="地址">
</el-table-column>
<el-table-column
prop="tag"
label="标签"
width="100"
:filters="[{ text: '家', value: '家' }, { text: '公司', value: '公司' }]"
:filter-method="filterTag"
filter-placement="bottom-end">
<template slot-scope="scope">
<el-tag
:type="scope.row.tag === '家' ? 'primary' : 'success'"
disable-transitions>{{scope.row.tag}}</el-tag>
</template>
</el-table-column>
<el-table-column label="操作">
<template slot-scope="scope">
<el-button
size="mini"
@click="handleEdit(scope.$index, scope.row)">编辑</el-button>
<el-button
size="mini"
type="danger"
@click="handleDelete(scope.$index, scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
</template>
</div>
</template>
<script>
import Sortable from 'sortablejs'
export default {
name: 'dragTabe',
data () {
return {
tableData: [{
date: '2016-05-03',
name: '王小虎',
province: '上海',
city: '普陀区',
address: '上海市普陀区金沙江路 1518 弄',
zip: 200333,
tag: '家'
}, {
date: '2016-05-02',
name: '王小虎',
province: '上海',
city: '普陀区',
address: '上海市普陀区金沙江路 1518 弄',
zip: 200333,
tag: '公司'
}, {
date: '2016-05-04',
name: '王小虎',
province: '上海',
city: '普陀区',
address: '上海市普陀区金沙江路 1518 弄',
zip: 200333,
tag: '家'
}, {
date: '2016-05-01',
name: '王小虎',
province: '上海',
city: '普陀区',
address: '上海市普陀区金沙江路 1518 弄',
zip: 200333,
tag: '公司'
}]
}
},
methods: {
handleEdit (index, row) {
console.log(index, row);
},
handleDelete (index, row) {
console.log(index, row);
},
filterTag (value, row) {
return row.tag === value;
},
},
mounted () {
let el = document.querySelectorAll('.el-table__body-wrapper > table > tbody')[0]
this.sortable = Sortable.create(el)
}
}
</script>
<style>
.sortable-ghost{
opacity: .9;
}
.sortable-ghost td{
border-top: 1px dashed #666666 !important;
border-bottom: 1px dashed #666666 !important;
color: #fff!important;
}
.sortable-ghost td:first-child{
border-left: 1px dashed #666666 !important;
}
.sortable-ghost td:last-child{
border-right: 1px dashed #666666 !important;
border-bottom: 1px dashed #666666 !important;
}
</style>
<style lang="scss">
p.dragtabe{
margin-top: 30px;
}
</style>

View File

@@ -0,0 +1,118 @@
<template>
<div>
<h3>筛选</h3>
<p>对表格进行筛选可快速查找到自己想看的数据</p>
<template>
<el-table
:data="tableData5"
style="width: 100%">
<el-table-column
prop="date"
label="日期"
sortable
width="180"
:filters="[{text: '2016-05-01', value: '2016-05-01'}, {text: '2016-05-02', value: '2016-05-02'}, {text: '2016-05-03', value: '2016-05-03'}, {text: '2016-05-04', value: '2016-05-04'}]"
:filter-method="filterHandler"
>
</el-table-column>
<el-table-column
prop="name"
label="姓名"
width="180">
</el-table-column>
<el-table-column
prop="address"
label="地址"
:formatter="formatter">
</el-table-column>
<el-table-column
prop="tag"
label="标签"
width="100"
:filters="[{ text: '家', value: '家' }, { text: '公司', value: '公司' }]"
:filter-method="filterTag"
filter-placement="bottom-end">
<template slot-scope="scope">
<el-tag
:type="scope.row.tag === '家' ? 'primary' : 'success'"
disable-transitions>{{scope.row.tag}}</el-tag>
</template>
</el-table-column>
<el-table-column label="操作">
<template slot-scope="scope">
<el-button
size="mini"
@click="handleEdit(scope.$index, scope.row)">编辑</el-button>
<el-button
size="mini"
type="danger"
@click="handleDelete(scope.$index, scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
</template>
</div>
</template>
<script>
export default {
name: 'filterTable',
data () {
return {
tableData5: [{
date: '2016-05-02',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄',
tag: '家'
}, {
date: '2016-05-04',
name: '王小虎',
address: '上海市普陀区金沙江路 1517 弄',
tag: '公司'
}, {
date: '2016-05-01',
name: '王小虎',
address: '上海市普陀区金沙江路 1519 弄',
tag: '家'
}, {
date: '2016-05-03',
name: '王小虎',
address: '上海市普陀区金沙江路 1516 弄',
tag: '公司'
}]
}
},
methods: {
handleEdit (index, row) {
console.log(index, row)
this.$message({
showClose: true,
message: index, row,
type: 'success'
})
},
handleDelete (index, row) {
console.log(index, row)
this.$message({
showClose: true,
message: index, row,
type: 'success'
})
},
filterHandler (value, row, column) {
const property = column['property']
return row[property] === value
},
formatter (row, column) {
return row.address
},
filterTag (value, row) {
return row.tag === value
}
}
}
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,176 @@
<template>
<div>
<p class="title"><i class="el-icon-tickets"></i>最新10条等待处理订单</p>
<el-table
border
:data="tableData"
style="width: 100%">
<el-table-column
type="index">
</el-table-column>
<el-table-column
sortable
prop="odd"
label="订单号">
</el-table-column>
<el-table-column
prop="name"
label="收货人">
</el-table-column>
<el-table-column
prop="status"
label="订单状态"
width="130">
</el-table-column>
<el-table-column
prop="amount"
label="金额">
</el-table-column>
<el-table-column
prop="date"
label="下单时间"
sortable
:filters="[{text: '2018-01-01', value: '2018-01-01'}, {text: '2018-01-02', value: '2018-01-02'}, {text: '2018-01-03', value: '2018-01-03'}, {text: '2018-01-04', value: '2018-01-04'}, {text: '2018-01-05', value: '2018-01-05'}]"
:filter-method="filterHandler"
>
</el-table-column>
<el-table-column
prop="tag"
label="订单分类"
width="150"
:filters="[{ text: '虚拟', value: '虚拟' }, { text: '实物', value: '实物' }]"
:filter-method="filterTag"
filter-placement="bottom-end">
<template slot-scope="scope">
<el-tag
:type="scope.row.tag === '虚拟' ? 'primary' : 'success'"
disable-transitions>{{scope.row.tag}}</el-tag>
</template>
</el-table-column>
<el-table-column label="操作">
<template slot-scope="scope">
<el-button
size="mini"
@click="handleEdit(scope.$index, scope.row)">详情</el-button>
<el-button
size="mini"
type="danger"
@click="handleDelete(scope.$index, scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
</div>
</template>
<script>
export default {
name: 'maintable',
data () {
return {
tableData: [{
odd: '201801012345601',
name: '王小虎',
status: '已付款',
amount: '580元',
date: '2018-01-01',
tag: '虚拟'
}, {
odd: '201801012345602',
name: '王小虎',
status: '已付款',
amount: '130元',
date: '2018-01-02',
tag: '实物'
}, {
odd: '201801012345603',
name: '王小虎',
status: '已付款',
amount: '680元',
date: '2018-01-03',
tag: '虚拟'
}, {
odd: '201801012345604',
name: '王小虎',
status: '已付款',
amount: '190元',
date: '2018-01-03',
tag: '虚拟'
}, {
odd: '201801012345605',
name: '王小虎',
status: '已付款',
amount: '170元',
date: '2018-01-04',
tag: '实物'
}, {
odd: '201801012345606',
name: '王小虎',
status: '已付款',
amount: '670元',
date: '2018-01-04',
tag: '虚拟'
}, {
odd: '201801012345607',
name: '王小虎',
status: '已付款',
amount: '1780元',
date: '2018-01-04',
tag: '实物'
}, {
odd: '201801012345608',
name: '王小虎',
status: '已付款',
amount: '3180元',
date: '2018-01-04',
tag: '虚拟'
}, {
odd: '201801012345609',
name: '王小虎',
status: '已付款',
amount: '780元',
date: '2018-01-05',
tag: '实物'
}, {
odd: '201801012345610',
name: '王小虎',
status: '已付款',
amount: '2130元',
date: '2018-01-05',
tag: '虚拟'
}]
}
},
methods: {
handleEdit (index, row) {
console.log(index, row)
this.$message({
showClose: true,
message: index, row,
type: 'success'
})
},
handleDelete (index, row) {
console.log(index, row)
this.$message({
showClose: true,
message: index, row,
type: 'success'
})
},
formatter (row, column) {
return row.address
},
filterTag (value, row) {
return row.tag === value
},
filterHandler (value, row, column) {
const property = column['property']
return row[property] === value
}
}
}
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,146 @@
<template>
<div>
<h3>基础用法</h3>
<template>
<el-transfer v-model="value1" :data="data"></el-transfer>
</template>
<h3>可搜索</h3>
<p>在数据很多的情况下可以对数据进行搜索和过滤</p>
<template>
<el-transfer
filterable
:filter-method="filterMethod"
filter-placeholder="请输入城市拼音"
v-model="value2"
:data="data2">
</el-transfer>
</template>
<h3>可自定义</h3>
<p>可以对列表标题文案按钮文案数据项的渲染函数列表底部的勾选状态文案列表底部的内容区等进行自定义</p>
<template>
<p style="text-align: center; margin: 0 0 20px">使用 render-content 自定义数据项</p>
<div style="text-align: center">
<el-transfer
style="text-align: left; display: inline-block"
v-model="value3"
filterable
:left-default-checked="[2, 3]"
:right-default-checked="[1]"
:render-content="renderFunc"
:titles="['Source', 'Target']"
:button-texts="['到左边', '到右边']"
:format="{
noChecked: '${total}',
hasChecked: '${checked}/${total}'
}"
@change="handleChange"
:data="data3">
<el-button class="transfer-footer" slot="left-footer" size="small">操作</el-button>
<el-button class="transfer-footer" slot="right-footer" size="small">操作</el-button>
</el-transfer>
</div>
<p style="text-align: center; margin: 50px 0 20px">使用 scoped-slot 自定义数据项</p>
<div style="text-align: center">
<el-transfer
style="text-align: left; display: inline-block"
v-model="value4"
filterable
:left-default-checked="[2, 3]"
:right-default-checked="[1]"
:titles="['Source', 'Target']"
:button-texts="['到左边', '到右边']"
:format="{
noChecked: '${total}',
hasChecked: '${checked}/${total}'
}"
@change="handleChange"
:data="data">
<span slot-scope="{ option }">{{ option.key }} - {{ option.label }}</span>
<el-button class="transfer-footer" slot="left-footer" size="small">操作</el-button>
<el-button class="transfer-footer" slot="right-footer" size="small">操作</el-button>
</el-transfer>
</div>
</template>
</div>
</template>
<script>
export default {
name: 'transfer',
data () {
const generateData = _ => {
const data = []
for (let i = 1; i <= 15; i++) {
data.push({
key: i,
label: `备选项 ${i}`,
disabled: i % 4 === 0
})
}
return data
}
const generateData2 = _ => {
const data = []
const cities = ['上海', '北京', '广州', '深圳', '南京', '西安', '成都']
const pinyin = ['shanghai', 'beijing', 'guangzhou', 'shenzhen', 'nanjing', 'xian', 'chengdu']
cities.forEach((city, index) => {
data.push({
label: city,
key: index,
pinyin: pinyin[index]
})
})
return data
}
const generateData3 = _ => {
const data = []
for (let i = 1; i <= 15; i++) {
data.push({
key: i,
label: `备选项 ${i}`,
disabled: i % 4 === 0
})
}
return data
}
return {
data: generateData(),
value1: [1, 4],
data2: generateData2(),
value2: [],
filterMethod (query, item) {
return item.pinyin.indexOf(query) > -1
},
data3: generateData3(),
value3: [1],
value4: [1],
renderFunc (h, option) {
return <span>{ option.key } - { option.label }</span>
}
}
},
methods: {
handleChange (value, direction, movedKeys) {
console.log(value, direction, movedKeys)
}
}
}
</script>
<style scoped>
h3{
margin: 55px 0 20px;
font-weight: 400;
color: #1f2f3d;
font-size: 22px;
}
p{
font-size: 14px;
color: #5e6d82;
line-height: 1.5em;
}
.transfer-footer {
margin-left: 20px;
padding: 6px 5px;
}
</style>

135
src/views/upload/upload.vue Normal file
View File

@@ -0,0 +1,135 @@
<template>
<div>
<h3>点击上传</h3>
<el-upload
class="upload-demo"
action="https://jsonplaceholder.typicode.com/posts/"
:on-preview="handlePreview"
:on-remove="handleRemove"
:before-remove="beforeRemove"
multiple
:limit="3"
:on-exceed="handleExceed"
:file-list="fileList">
<el-button size="small" type="primary">点击上传</el-button>
<div slot="tip" class="el-upload__tip">只能上传jpg/png文件且不超过500kb</div>
</el-upload>
<h3>用户头像上传</h3>
<p>使用 before-upload 限制用户上传的图片格式和大小</p>
<el-upload
class="avatar-uploader"
action="https://jsonplaceholder.typicode.com/posts/"
:show-file-list="false"
:on-success="handleAvatarSuccess"
:before-upload="beforeAvatarUpload">
<img v-if="imageUrl" :src="imageUrl" class="avatar">
<i v-else class="el-icon-plus avatar-uploader-icon"></i>
</el-upload>
<h3>照片墙</h3>
<p>使用 list-type 属性来设置文件列表的样式</p>
<el-upload
action="https://jsonplaceholder.typicode.com/posts/"
list-type="picture-card"
:on-preview="handlePictureCardPreview"
:on-remove="handleRemove">
<i class="el-icon-plus"></i>
</el-upload>
<el-dialog :visible.sync="dialogVisible">
<img width="100%" :src="dialogImageUrl" alt="">
</el-dialog>
<h3>拖拽上传</h3>
<el-upload
class="upload-demo"
drag
action="https://jsonplaceholder.typicode.com/posts/"
multiple>
<i class="el-icon-upload"></i>
<div class="el-upload__text">将文件拖到此处<em>点击上传</em></div>
<div class="el-upload__tip" slot="tip">只能上传jpg/png文件且不超过500kb</div>
</el-upload>
</div>
</template>
<script>
export default {
name: 'upload',
data () {
return {
fileList: [{name: 'food.jpeg', url: 'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100'}, {name: 'food2.jpeg', url: 'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100'}],
imageUrl: '',
dialogImageUrl: '',
dialogVisible: false
}
},
methods: {
handleRemove (file, fileList) {
console.log(file, fileList)
},
handlePreview (file) {
console.log(file)
},
handleExceed (files, fileList) {
this.$message.warning(`当前限制选择 3 个文件,本次选择了 ${files.length} 个文件,共选择了 ${files.length + fileList.length} 个文件`)
},
beforeRemove (file, fileList) {
return this.$confirm(`确定移除 ${file.name}`)
},
handleAvatarSuccess(res, file) {
this.imageUrl = URL.createObjectURL(file.raw);
},
beforeAvatarUpload(file) {
const isJPG = file.type === 'image/jpeg';
const isLt2M = file.size / 1024 / 1024 < 2;
if (!isJPG) {
this.$message.error('上传头像图片只能是 JPG 格式!');
}
if (!isLt2M) {
this.$message.error('上传头像图片大小不能超过 2MB!');
}
return isJPG && isLt2M;
},
handlePictureCardPreview(file) {
this.dialogImageUrl = file.url;
this.dialogVisible = true;
}
}
}
</script>
<style lang="scss">
.avatar-uploader .el-upload {
border: 1px dashed #d9d9d9;
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
}
.avatar-uploader .el-upload:hover {
border-color: #409EFF;
}
.avatar-uploader-icon {
font-size: 28px;
color: #8c939d;
width: 178px;
height: 178px;
line-height: 178px;
text-align: center;
}
.avatar {
width: 178px;
height: 178px;
display: block;
}
h3{
margin: 55px 0 20px;
font-weight: 400;
color: #1f2f3d;
font-size: 22px;
}
p{
font-size: 14px;
color: #5e6d82;
line-height: 1.5em;
}
</style>

49
src/vuex/index.js Normal file
View File

@@ -0,0 +1,49 @@
import Vue from 'vue'
import Vuex from 'vuex'
import Cookies from 'js-cookie'
import routerData from './modules/routerData'
import role from './modules/role'
import layout from './modules/layout/index'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
token: Cookies.get('token')
},
mutations: {
setToken (state, token) {
state.token = token
Cookies.set('token', token ,{ expires: 1/24 });
}
},
actions: {
setToken ({commit}, token) {
return new Promise((resolve, reject) => {
commit('setToken', token)
resolve()
})
}
},
getters: {
addRouters: state => state.routerData.addRouters,
token: state => state.token,
info: state => state.role.info,
routers: state => state.routerData.routers,
logoShow: state => state.layout.logoShow,
isCollapse: state => state.layout.isCollapse,
uniquerouter: state => state.layout.uniquerouter,
tabnavBox: state => state.layout.tabnavBox,
visible: state => state.layout.visible,
left: state => state.layout.left,
top: state => state.layout.top,
rightNav: state => state.layout.rightNav,
},
modules: {
routerData,
role,
layout
},
})
export default store

View File

@@ -0,0 +1,86 @@
/**
* Created by WebStorm.
* User: nirongxu
* Date: 2018/12/10
* Description: 文件描述
*/
export default {
state: {
isCollapse: false,
logoShow: false,
uniquerouter: true,
rightNav: {},
tabnavBox: [
{
title: 'home',
path: '/index'
}
]
},
mutations: {
addTab (state, arg) {
state.isActive = arg.path
for (let i = 0; i < state.tabnavBox.length; i++) {
if (state.tabnavBox[i].path === arg.path) {
return false
}
}
state.tabnavBox.push({
title: arg.title,
path: arg.path
})
},
openMenu (state, arg) {
state.rightNav = arg
},
removeTab (state, arg) {
let index = state.tabnavBox.findIndex(function (value, key) {
return value.path === arg.tabItem.path
})
state.tabnavBox.splice(index, 1)
if (arg.tabItem.path === arg.fullPath) {
let tabActive = state.tabnavBox[index] || state.tabnavBox[index - 1]
arg.router.push(tabActive.path)
}
},
removeOtherTab (state, arg) {
state.tabnavBox = [{
title: 'home',
path: '/index'
}]
if (arg.all) {
arg.router.push('/index')
return false
}
state.tabnavBox.push(arg.tabItem)
arg.router.push(arg.tabItem.path)
},
collapse (state, arg) {
state.isCollapse = !state.isCollapse
if (state.logoShow) {
setTimeout(function () {
state.logoShow = false
}, 300)
} else {
state.logoShow = true
}
},
},
actions: {
addTab ({commit}, arg) {
commit('addTab', arg)
},
openMenu ({commit}, arg) {
commit('openMenu', arg)
},
removeTab ({commit}, arg) {
commit('removeTab', arg)
},
removeOtherTab ({commit}, arg) {
commit('removeOtherTab', arg)
},
collapse ({commit}, arg) {
commit('collapse', arg)
},
}
}

32
src/vuex/modules/role.js Normal file
View File

@@ -0,0 +1,32 @@
import store from '../index'
import router from '../../router/index'
export default {
state: {
info: '' // 每次刷新都要通过token请求个人信息来筛选动态路由
},
mutations: {
getInfo (state, info) {
state.info = info
sessionStorage.setItem('info', JSON.stringify(store.getters.info))
},
setRole (state, options) { // 切换角色,测试权限管理
state.info = {
role: options.role,
permissions: options.permissions
}
sessionStorage.setItem('info', JSON.stringify(store.getters.info));
store.dispatch('newRoutes', options.role)
router.addRoutes(store.getters.addRouters)
}
},
actions: {
getInfo ({commit}, token) {
commit('getInfo', token)
},
setRole ({commit}, options){
// 权限测试
commit('setRole', options)
}
}
}

View File

@@ -0,0 +1,41 @@
import {defaultRouter, addRouter} from '@/router/index'
const routerData = {
state: {
routers: [],
addRouters: []
},
mutations: {
setRouters: (state, routers) => {
state.addRouters = routers // 保存动态路由用来addRouter
state.routers = defaultRouter.concat(routers) // 所有有权限的路由表,用来生成菜单列表
}
},
actions: {
newRoutes ({commit}, role) {
// 通过递归路由表,删除掉没有权限的路由
function eachSelect (routers, userRole) {
for (let j = 0; j < routers.length; j++) {
if (routers[j].meta && routers[j].meta.role.length && routers[j].meta.role.indexOf(userRole) === -1) {
routers.splice(j, 1)
j = j !== 0 ? j - 1 : j
}
if (routers[j].children && routers[j].children.length) {
eachSelect(routers[j].children, userRole)
}
}
}
// 拷贝这个数组是因为做权限测试的时候可以从低级切回到高级角色,仅限演示,正式开发时省略这步直接使用 addRouter
// 仅限演示
let newArr = [...addRouter]
eachSelect(newArr, role)
commit('setRouters', newArr)
// 正式开发
// eachSelect(addRouter, role)
// commit('setRouters', addRouter)
}
}
}
export default routerData