Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
VueElementTemplate
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
JIRA
JIRA
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
HireTest
VueElementTemplate
Commits
de992c50
Commit
de992c50
authored
Jul 06, 2017
by
Pan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
全局代码格式 优化
parent
622a8c3a
Changes
73
Hide whitespace changes
Inline
Side-by-side
Showing
73 changed files
with
3124 additions
and
3119 deletions
+3124
-3119
App.vue
src/App.vue
+6
-6
401.gif
src/assets/401_images/401.gif
+0
-0
404.png
src/assets/404_images/404.png
+0
-0
404_cloud.png
src/assets/404_images/404_cloud.png
+0
-0
keyboard.vue
src/components/Charts/keyboard.vue
+2
-1
keyboard2.vue
src/components/Charts/keyboard2.vue
+2
-1
lineMarker.vue
src/components/Charts/lineMarker.vue
+2
-1
mixchart.vue
src/components/Charts/mixchart.vue
+2
-1
index.vue
src/components/Dropzone/index.vue
+170
-169
index.vue
src/components/ErrLog/index.vue
+44
-39
index.vue
src/components/Hamburger/index.vue
+36
-26
index.vue
src/components/MDinput/index.vue
+131
-131
index.vue
src/components/MdEditor/index.vue
+90
-87
index.vue
src/components/PanThumb/index.vue
+121
-126
index.vue
src/components/Screenfull/index.vue
+40
-37
Pane.vue
src/components/SplitPane/Pane.vue
+36
-33
Resizer.vue
src/components/SplitPane/Resizer.vue
+58
-57
index.vue
src/components/SplitPane/index.vue
+94
-94
index.vue
src/components/Sticky/index.vue
+63
-62
index.vue
src/components/Tinymce/index.vue
+103
-103
singleImage.vue
src/components/Upload/singleImage.vue
+48
-54
singleImage2.vue
src/components/Upload/singleImage2.vue
+111
-118
singleImage3.vue
src/components/Upload/singleImage3.vue
+138
-146
index.vue
src/components/jsonEditor/index.vue
+48
-48
index.vue
src/components/twoDndList/index.vue
+114
-112
index.js
src/filters/index.js
+0
-5
main.js
src/main.js
+2
-4
login.js
src/mock/login.js
+3
-7
index.js
src/router/index.js
+0
-2
getters.js
src/store/getters.js
+0
-3
user.js
src/store/modules/user.js
+1
-17
keyboard.vue
src/views/charts/keyboard.vue
+5
-4
keyboard2.vue
src/views/charts/keyboard2.vue
+5
-4
line.vue
src/views/charts/line.vue
+5
-4
mixchart.vue
src/views/charts/mixchart.vue
+5
-4
avatarUpload.vue
src/views/components/avatarUpload.vue
+30
-29
countTo.vue
src/views/components/countTo.vue
+67
-67
dndlist.vue
src/views/components/dndlist.vue
+26
-24
dropzone.vue
src/views/components/dropzone.vue
+15
-15
jsoneditor.vue
src/views/components/jsoneditor.vue
+10
-9
markdown.vue
src/views/components/markdown.vue
+18
-18
mixin.vue
src/views/components/mixin.vue
+14
-14
splitpane.vue
src/views/components/splitpane.vue
+52
-49
sticky.vue
src/views/components/sticky.vue
+20
-19
tinymce.vue
src/views/components/tinymce.vue
+8
-8
index.vue
src/views/dashboard/default/index.vue
+72
-72
barChart.vue
src/views/dashboard/editor/barChart.vue
+2
-1
index.vue
src/views/dashboard/editor/index.vue
+95
-95
lineChart.vue
src/views/dashboard/editor/lineChart.vue
+2
-2
pieChart.vue
src/views/dashboard/editor/pieChart.vue
+2
-1
index.vue
src/views/dashboard/index.vue
+29
-32
index.vue
src/views/errlog/index.vue
+9
-13
401.vue
src/views/error/401.vue
+17
-17
404.vue
src/views/error/404.vue
+175
-165
form.vue
src/views/example/form.vue
+115
-115
dragTable.vue
src/views/example/table/dragTable.vue
+53
-53
dynamictable.vue
src/views/example/table/dynamictable.vue
+2
-2
inlineEditTable.vue
src/views/example/table/inlineEditTable.vue
+37
-37
table.vue
src/views/example/table/table.vue
+180
-180
index.vue
src/views/excel/index.vue
+34
-31
index.vue
src/views/introduction/index.vue
+1
-1
AppMain.vue
src/views/layout/AppMain.vue
+12
-12
Layout.vue
src/views/layout/Layout.vue
+69
-69
Levelbar.vue
src/views/layout/Levelbar.vue
+31
-31
Navbar.vue
src/views/layout/Navbar.vue
+105
-105
Sidebar.vue
src/views/layout/Sidebar.vue
+15
-15
SidebarItem.vue
src/views/layout/SidebarItem.vue
+36
-36
TabsView.vue
src/views/layout/TabsView.vue
+26
-27
index.vue
src/views/login/index.vue
+120
-123
socialsignin.vue
src/views/login/socialsignin.vue
+58
-56
index.vue
src/views/permission/index.vue
+18
-18
upload.vue
src/views/qiniu/upload.vue
+25
-30
index.vue
src/views/theme/index.vue
+39
-22
No files found.
src/App.vue
View file @
de992c50
<
template
>
<div
id=
"app"
>
<router-view></router-view>
</div>
<div
id=
"app"
>
<router-view></router-view>
</div>
</
template
>
<
script
>
export
default
{
name
:
'APP'
}
export
default
{
name
:
'APP'
}
</
script
>
<
style
lang=
"scss"
>
...
...
src/assets/401.gif
→
src/assets/401
_images/401
.gif
View file @
de992c50
File moved
src/assets/404.png
→
src/assets/404
_images/404
.png
View file @
de992c50
File moved
src/assets/404_cloud.png
→
src/assets/404_
images/404_
cloud.png
View file @
de992c50
File moved
src/components/Charts/keyboard.vue
View file @
de992c50
<
template
>
<div
:class=
"className"
:id=
"id"
:style=
"
{height:height,width:width}">
</div>
<div
:class=
"className"
:id=
"id"
:style=
"
{height:height,width:width}">
</div>
</
template
>
<
script
>
import
echarts
from
'echarts'
;
...
...
src/components/Charts/keyboard2.vue
View file @
de992c50
<
template
>
<div
:class=
"className"
:id=
"id"
:style=
"
{height:height,width:width}">
</div>
<div
:class=
"className"
:id=
"id"
:style=
"
{height:height,width:width}">
</div>
</
template
>
<
script
>
import
echarts
from
'echarts'
;
...
...
src/components/Charts/lineMarker.vue
View file @
de992c50
<
template
>
<div
:class=
"className"
:id=
"id"
:style=
"
{height:height,width:width}">
</div>
<div
:class=
"className"
:id=
"id"
:style=
"
{height:height,width:width}">
</div>
</
template
>
<
script
>
import
echarts
from
'echarts'
;
...
...
src/components/Charts/mixchart.vue
View file @
de992c50
<
template
>
<div
:class=
"className"
:id=
"id"
:style=
"
{height:height,width:width}">
</div>
<div
:class=
"className"
:id=
"id"
:style=
"
{height:height,width:width}">
</div>
</
template
>
<
script
>
import
echarts
from
'echarts'
;
...
...
src/components/Dropzone/index.vue
View file @
de992c50
<
template
>
<div
:ref=
"id"
:action=
"url"
class=
"dropzone"
:id=
"id"
>
<input
type=
"file"
name=
"file"
>
</div>
<div
:ref=
"id"
:action=
"url"
class=
"dropzone"
:id=
"id"
>
<input
type=
"file"
name=
"file"
>
</div>
</
template
>
<
script
>
import
Dropzone
from
'dropzone'
;
import
'dropzone/dist/dropzone.css'
;
import
Dropzone
from
'dropzone'
;
import
'dropzone/dist/dropzone.css'
;
// import { getToken } from 'api/qiniu';
Dropzone
.
autoDiscover
=
false
;
Dropzone
.
autoDiscover
=
false
;
export
default
{
data
()
{
return
{
dropzone
:
''
,
initOnce
:
true
}
},
mounted
()
{
const
element
=
document
.
getElementById
(
this
.
id
);
const
vm
=
this
;
this
.
dropzone
=
new
Dropzone
(
element
,
{
clickable
:
this
.
clickable
,
thumbnailWidth
:
this
.
thumbnailWidth
,
thumbnailHeight
:
this
.
thumbnailHeight
,
maxFiles
:
this
.
maxFiles
,
maxFilesize
:
this
.
maxFilesize
,
dictRemoveFile
:
'Remove'
,
addRemoveLinks
:
this
.
showRemoveLink
,
acceptedFiles
:
this
.
acceptedFiles
,
autoProcessQueue
:
this
.
autoProcessQueue
,
dictDefaultMessage
:
'<i style="margin-top: 3em;display: inline-block" class="material-icons">'
+
this
.
defaultMsg
+
'</i><br>Drop files here to upload'
,
dictMaxFilesExceeded
:
'只能一个图'
,
previewTemplate
:
'<div class="dz-preview dz-file-preview"> <div class="dz-image" style="width:'
+
this
.
thumbnailWidth
+
'px;height:'
+
this
.
thumbnailHeight
+
'px" ><img style="width:'
+
this
.
thumbnailWidth
+
'px;height:'
+
this
.
thumbnailHeight
+
'px" data-dz-thumbnail /></div> <div class="dz-details"><div class="dz-size"><span data-dz-size></span></div> <div class="dz-progress"><span class="dz-upload" data-dz-uploadprogress></span></div> <div class="dz-error-message"><span data-dz-errormessage></span></div> <div class="dz-success-mark"> <i class="material-icons">done</i> </div> <div class="dz-error-mark"><i class="material-icons">error</i></div></div>'
,
init
()
{
const
val
=
vm
.
defaultImg
;
if
(
!
val
)
return
;
if
(
Array
.
isArray
(
val
))
{
if
(
val
.
length
===
0
)
return
;
val
.
map
((
v
,
i
)
=>
{
const
mockFile
=
{
name
:
'name'
+
i
,
size
:
12345
,
url
:
v
};
this
.
options
.
addedfile
.
call
(
this
,
mockFile
);
this
.
options
.
thumbnail
.
call
(
this
,
mockFile
,
v
);
mockFile
.
previewElement
.
classList
.
add
(
'dz-success'
);
mockFile
.
previewElement
.
classList
.
add
(
'dz-complete'
);
vm
.
initOnce
=
false
;
return
true
;
})
}
else
{
const
mockFile
=
{
name
:
'name'
,
size
:
12345
,
url
:
val
};
export
default
{
data
()
{
return
{
dropzone
:
''
,
initOnce
:
true
}
},
mounted
()
{
const
element
=
document
.
getElementById
(
this
.
id
);
const
vm
=
this
;
this
.
dropzone
=
new
Dropzone
(
element
,
{
clickable
:
this
.
clickable
,
thumbnailWidth
:
this
.
thumbnailWidth
,
thumbnailHeight
:
this
.
thumbnailHeight
,
maxFiles
:
this
.
maxFiles
,
maxFilesize
:
this
.
maxFilesize
,
dictRemoveFile
:
'Remove'
,
addRemoveLinks
:
this
.
showRemoveLink
,
acceptedFiles
:
this
.
acceptedFiles
,
autoProcessQueue
:
this
.
autoProcessQueue
,
dictDefaultMessage
:
'<i style="margin-top: 3em;display: inline-block" class="material-icons">'
+
this
.
defaultMsg
+
'</i><br>Drop files here to upload'
,
dictMaxFilesExceeded
:
'只能一个图'
,
previewTemplate
:
'<div class="dz-preview dz-file-preview"> <div class="dz-image" style="width:'
+
this
.
thumbnailWidth
+
'px;height:'
+
this
.
thumbnailHeight
+
'px" ><img style="width:'
+
this
.
thumbnailWidth
+
'px;height:'
+
this
.
thumbnailHeight
+
'px" data-dz-thumbnail /></div> <div class="dz-details"><div class="dz-size"><span data-dz-size></span></div> <div class="dz-progress"><span class="dz-upload" data-dz-uploadprogress></span></div> <div class="dz-error-message"><span data-dz-errormessage></span></div> <div class="dz-success-mark"> <i class="material-icons">done</i> </div> <div class="dz-error-mark"><i class="material-icons">error</i></div></div>'
,
init
()
{
const
val
=
vm
.
defaultImg
;
if
(
!
val
)
return
;
if
(
Array
.
isArray
(
val
))
{
if
(
val
.
length
===
0
)
return
;
val
.
map
((
v
,
i
)
=>
{
const
mockFile
=
{
name
:
'name'
+
i
,
size
:
12345
,
url
:
v
};
this
.
options
.
addedfile
.
call
(
this
,
mockFile
);
this
.
options
.
thumbnail
.
call
(
this
,
mockFile
,
v
al
);
this
.
options
.
thumbnail
.
call
(
this
,
mockFile
,
v
);
mockFile
.
previewElement
.
classList
.
add
(
'dz-success'
);
mockFile
.
previewElement
.
classList
.
add
(
'dz-complete'
);
vm
.
initOnce
=
false
;
}
},
accept
:
(
file
,
done
)
=>
{
return
true
;
})
}
else
{
const
mockFile
=
{
name
:
'name'
,
size
:
12345
,
url
:
val
};
this
.
options
.
addedfile
.
call
(
this
,
mockFile
);
this
.
options
.
thumbnail
.
call
(
this
,
mockFile
,
val
);
mockFile
.
previewElement
.
classList
.
add
(
'dz-success'
);
mockFile
.
previewElement
.
classList
.
add
(
'dz-complete'
);
vm
.
initOnce
=
false
;
}
},
accept
:
(
file
,
done
)
=>
{
/* 七牛*/
// const token = this.$store.getters.token;
// getToken(token).then(response => {
...
...
@@ -65,142 +66,142 @@
// file.url = response.data.qiniu_url;
// done();
// })
done
();
},
sending
:
(
file
,
xhr
,
formData
)
=>
{
done
();
},
sending
:
(
file
,
xhr
,
formData
)
=>
{
/* 七牛*/
console
.
log
(
file
,
xhr
,
formData
)
console
.
log
(
file
,
xhr
,
formData
)
// formData.append('token', file.token);
// formData.append('key', file.key);
vm
.
initOnce
=
false
;
}
});
if
(
this
.
couldPaste
)
{
document
.
addEventListener
(
'paste'
,
this
.
pasteImg
)
vm
.
initOnce
=
false
;
}
});
this
.
dropzone
.
on
(
'success'
,
file
=>
{
vm
.
$emit
(
'dropzone-success'
,
file
,
vm
.
dropzone
.
element
)
});
this
.
dropzone
.
on
(
'addedfile'
,
file
=>
{
vm
.
$emit
(
'dropzone-fileAdded'
,
file
)
});
this
.
dropzone
.
on
(
'removedfile'
,
file
=>
{
vm
.
$emit
(
'dropzone-removedFile'
,
file
)
});
this
.
dropzone
.
on
(
'error'
,
(
file
,
error
,
xhr
)
=>
{
vm
.
$emit
(
'dropzone-error'
,
file
,
error
,
xhr
)
});
this
.
dropzone
.
on
(
'successmultiple'
,
(
file
,
error
,
xhr
)
=>
{
vm
.
$emit
(
'dropzone-successmultiple'
,
file
,
error
,
xhr
)
});
if
(
this
.
couldPaste
)
{
document
.
addEventListener
(
'paste'
,
this
.
pasteImg
)
}
this
.
dropzone
.
on
(
'success'
,
file
=>
{
vm
.
$emit
(
'dropzone-success'
,
file
,
vm
.
dropzone
.
element
)
});
this
.
dropzone
.
on
(
'addedfile'
,
file
=>
{
vm
.
$emit
(
'dropzone-fileAdded'
,
file
)
});
this
.
dropzone
.
on
(
'removedfile'
,
file
=>
{
vm
.
$emit
(
'dropzone-removedFile'
,
file
)
});
this
.
dropzone
.
on
(
'error'
,
(
file
,
error
,
xhr
)
=>
{
vm
.
$emit
(
'dropzone-error'
,
file
,
error
,
xhr
)
});
this
.
dropzone
.
on
(
'successmultiple'
,
(
file
,
error
,
xhr
)
=>
{
vm
.
$emit
(
'dropzone-successmultiple'
,
file
,
error
,
xhr
)
});
},
methods
:
{
removeAllFiles
()
{
this
.
dropzone
.
removeAllFiles
(
true
)
},
methods
:
{
removeAllFiles
()
{
this
.
dropzone
.
removeAllFiles
(
true
)
},
processQueue
()
{
this
.
dropzone
.
processQueue
()
},
pasteImg
(
event
)
{
const
items
=
(
event
.
clipboardData
||
event
.
originalEvent
.
clipboardData
).
items
;
if
(
items
[
0
].
kind
===
'file'
)
{
this
.
dropzone
.
addFile
(
items
[
0
].
getAsFile
())
}
},
initImages
(
val
)
{
if
(
!
val
)
return
;
if
(
Array
.
isArray
(
val
))
{
val
.
map
((
v
,
i
)
=>
{
const
mockFile
=
{
name
:
'name'
+
i
,
size
:
12345
,
url
:
v
};
this
.
dropzone
.
options
.
addedfile
.
call
(
this
.
dropzone
,
mockFile
);
this
.
dropzone
.
options
.
thumbnail
.
call
(
this
.
dropzone
,
mockFile
,
v
);
mockFile
.
previewElement
.
classList
.
add
(
'dz-success'
);
mockFile
.
previewElement
.
classList
.
add
(
'dz-complete'
);
return
true
})
}
else
{
const
mockFile
=
{
name
:
'name'
,
size
:
12345
,
url
:
val
};
processQueue
()
{
this
.
dropzone
.
processQueue
()
},
pasteImg
(
event
)
{
const
items
=
(
event
.
clipboardData
||
event
.
originalEvent
.
clipboardData
).
items
;
if
(
items
[
0
].
kind
===
'file'
)
{
this
.
dropzone
.
addFile
(
items
[
0
].
getAsFile
())
}
},
initImages
(
val
)
{
if
(
!
val
)
return
;
if
(
Array
.
isArray
(
val
))
{
val
.
map
((
v
,
i
)
=>
{
const
mockFile
=
{
name
:
'name'
+
i
,
size
:
12345
,
url
:
v
};
this
.
dropzone
.
options
.
addedfile
.
call
(
this
.
dropzone
,
mockFile
);
this
.
dropzone
.
options
.
thumbnail
.
call
(
this
.
dropzone
,
mockFile
,
v
al
);
this
.
dropzone
.
options
.
thumbnail
.
call
(
this
.
dropzone
,
mockFile
,
v
);
mockFile
.
previewElement
.
classList
.
add
(
'dz-success'
);
mockFile
.
previewElement
.
classList
.
add
(
'dz-complete'
);
}
return
true
})
}
else
{
const
mockFile
=
{
name
:
'name'
,
size
:
12345
,
url
:
val
};
this
.
dropzone
.
options
.
addedfile
.
call
(
this
.
dropzone
,
mockFile
);
this
.
dropzone
.
options
.
thumbnail
.
call
(
this
.
dropzone
,
mockFile
,
val
);
mockFile
.
previewElement
.
classList
.
add
(
'dz-success'
);
mockFile
.
previewElement
.
classList
.
add
(
'dz-complete'
);
}
}
},
destroyed
()
{
document
.
removeEventListener
(
'paste'
,
this
.
pasteImg
);
this
.
dropzone
.
destroy
();
},
watch
:
{
defaultImg
(
val
)
{
if
(
val
.
length
===
0
)
{
this
.
initOnce
=
false
;
return
;
}
if
(
!
this
.
initOnce
)
return
;
this
.
initImages
(
val
);
},
destroyed
()
{
document
.
removeEventListener
(
'paste'
,
this
.
pasteImg
);
this
.
dropzone
.
destroy
();
},
watch
:
{
defaultImg
(
val
)
{
if
(
val
.
length
===
0
)
{
this
.
initOnce
=
false
;
return
;
}
if
(
!
this
.
initOnce
)
return
;
this
.
initImages
(
val
);
this
.
initOnce
=
false
;
}
},
props
:
{
id
:
{
type
:
String
,
required
:
true
},
props
:
{
id
:
{
type
:
String
,
required
:
true
},
url
:
{
type
:
String
,
required
:
true
},
clickable
:
{
type
:
Boolean
,
default
:
true
},
defaultMsg
:
{
type
:
String
,
default
:
'上传图片'
},
acceptedFiles
:
{
type
:
String
},
thumbnailHeight
:
{
type
:
Number
,
default
:
200
},
thumbnailWidth
:
{
type
:
Number
,
default
:
200
},
showRemoveLink
:
{
type
:
Boolean
,
default
:
true
},
maxFilesize
:
{
type
:
Number
,
default
:
2
},
maxFiles
:
{
type
:
Number
,
default
:
3
},
autoProcessQueue
:
{
type
:
Boolean
,
default
:
true
},
useCustomDropzoneOptions
:
{
type
:
Boolean
,
default
:
false
},
defaultImg
:
{
default
:
false
},
couldPaste
:
{
default
:
false
}
url
:
{
type
:
String
,
required
:
true
},
clickable
:
{
type
:
Boolean
,
default
:
true
},
defaultMsg
:
{
type
:
String
,
default
:
'上传图片'
},
acceptedFiles
:
{
type
:
String
},
thumbnailHeight
:
{
type
:
Number
,
default
:
200
},
thumbnailWidth
:
{
type
:
Number
,
default
:
200
},
showRemoveLink
:
{
type
:
Boolean
,
default
:
true
},
maxFilesize
:
{
type
:
Number
,
default
:
2
},
maxFiles
:
{
type
:
Number
,
default
:
3
},
autoProcessQueue
:
{
type
:
Boolean
,
default
:
true
},
useCustomDropzoneOptions
:
{
type
:
Boolean
,
default
:
false
},
defaultImg
:
{
default
:
false
},
couldPaste
:
{
default
:
false
}
}
}
</
script
>
<
style
scoped
>
...
...
src/components/ErrLog/index.vue
View file @
de992c50
<
template
>
<div>
<el-badge
:is-dot=
"true"
style=
"line-height: 30px;"
@
click
.
native=
"dialogTableVisible=true"
>
<el-button
size=
"small"
type=
"primary"
>
<svg
t=
"1492682037685"
class=
"bug-svg"
viewBox=
"0 0 1024 1024"
version=
"1.1"
xmlns=
"http://www.w3.org/2000/svg"
p-id=
"1863"
xmlns:xlink=
"http://www.w3.org/1999/xlink"
width=
"64"
height=
"64"
><path
d=
"M969.142857 548.571429q0 14.848-10.861714 25.709714t-25.709714 10.861714l-128 0q0 97.718857-38.290286 165.705143l118.857143 119.442286q10.861714 10.861714 10.861714 25.709714t-10.861714 25.709714q-10.276571 10.861714-25.709714 10.861714t-25.709714-10.861714l-113.152-112.566857q-2.852571 2.852571-8.557714 7.424t-23.990857 16.274286-37.156571 20.845714-46.848 16.566857-55.442286 7.424l0-512-73.142857 0 0 512q-29.147429 0-58.002286-7.716571t-49.700571-18.870857-37.705143-22.272-24.868571-18.578286l-8.557714-8.009143-104.557714 118.272q-11.446857 11.995429-27.428571 11.995429-13.714286 0-24.576-9.142857-10.861714-10.276571-11.702857-25.417143t8.850286-26.587429l115.419429-129.718857q-33.133714-65.133714-33.133714-156.562286l-128 0q-14.848 0-25.709714-10.861714t-10.861714-25.709714 10.861714-25.709714 25.709714-10.861714l128 0 0-168.009143-98.852571-98.852571q-10.861714-10.861714-10.861714-25.709714t10.861714-25.709714 25.709714-10.861714 25.709714 10.861714l98.852571 98.852571 482.304 0 98.852571-98.852571q10.861714-10.861714 25.709714-10.861714t25.709714 10.861714 10.861714 25.709714-10.861714 25.709714l-98.852571 98.852571 0 168.009143 128 0q14.848 0 25.709714 10.861714t10.861714 25.709714zM694.857143 219.428571l-365.714286 0q0-75.995429 53.430857-129.426286t129.426286-53.430857 129.426286 53.430857 53.430857 129.426286z"
p-id=
"1864"
></path></svg>
</el-button>
</el-badge>
<el-dialog
title=
"bug日志"
:visible
.
sync=
"dialogTableVisible"
>
<el-table
:data=
"logsList"
>
<el-table-column
label=
"message"
>
<template
scope=
"scope"
>
<div>
msg:
{{
scope
.
row
.
err
.
message
}}
</div>
<br/>
<div>
url:
{{
scope
.
row
.
url
}}
</div>
</
template
>
</el-table-column>
<el-table-column
label=
"stack"
>
<
template
scope=
"scope"
>
{{
scope
.
row
.
err
.
stack
}}
</
template
>
</el-table-column>
<div>
<el-badge
:is-dot=
"true"
style=
"line-height: 30px;"
@
click
.
native=
"dialogTableVisible=true"
>
<el-button
size=
"small"
type=
"primary"
>
<svg
t=
"1492682037685"
class=
"bug-svg"
viewBox=
"0 0 1024 1024"
version=
"1.1"
xmlns=
"http://www.w3.org/2000/svg"
p-id=
"1863"
xmlns:xlink=
"http://www.w3.org/1999/xlink"
width=
"64"
height=
"64"
>
<path
d=
"M969.142857 548.571429q0 14.848-10.861714 25.709714t-25.709714 10.861714l-128 0q0 97.718857-38.290286 165.705143l118.857143 119.442286q10.861714 10.861714 10.861714 25.709714t-10.861714 25.709714q-10.276571 10.861714-25.709714 10.861714t-25.709714-10.861714l-113.152-112.566857q-2.852571 2.852571-8.557714 7.424t-23.990857 16.274286-37.156571 20.845714-46.848 16.566857-55.442286 7.424l0-512-73.142857 0 0 512q-29.147429 0-58.002286-7.716571t-49.700571-18.870857-37.705143-22.272-24.868571-18.578286l-8.557714-8.009143-104.557714 118.272q-11.446857 11.995429-27.428571 11.995429-13.714286 0-24.576-9.142857-10.861714-10.276571-11.702857-25.417143t8.850286-26.587429l115.419429-129.718857q-33.133714-65.133714-33.133714-156.562286l-128 0q-14.848 0-25.709714-10.861714t-10.861714-25.709714 10.861714-25.709714 25.709714-10.861714l128 0 0-168.009143-98.852571-98.852571q-10.861714-10.861714-10.861714-25.709714t10.861714-25.709714 25.709714-10.861714 25.709714 10.861714l98.852571 98.852571 482.304 0 98.852571-98.852571q10.861714-10.861714 25.709714-10.861714t25.709714 10.861714 10.861714 25.709714-10.861714 25.709714l-98.852571 98.852571 0 168.009143 128 0q14.848 0 25.709714 10.861714t10.861714 25.709714zM694.857143 219.428571l-365.714286 0q0-75.995429 53.430857-129.426286t129.426286-53.430857 129.426286 53.430857 53.430857 129.426286z"
p-id=
"1864"
></path>
</svg>
</el-button>
</el-badge>
<el-dialog
title=
"bug日志"
:visible
.
sync=
"dialogTableVisible"
>
<el-table
:data=
"logsList"
>
<el-table-column
label=
"message"
>
<template
scope=
"scope"
>
<div>
msg:
{{
scope
.
row
.
err
.
message
}}
</div>
<br/>
<div>
url:
{{
scope
.
row
.
url
}}
</div>
</
template
>
</el-table-column>
<el-table-column
label=
"stack"
>
<
template
scope=
"scope"
>
{{
scope
.
row
.
err
.
stack
}}
</
template
>
</el-table-column>
</el-table>
</el-dialog>
</div>
</el-table>
</el-dialog>
</div>
</template>
<
script
>
export
default
{
name
:
'errLog'
,
props
:
{
logsList
:
{
type
:
Array
}
},
data
()
{
return
{
dialogTableVisible
:
false
}
export
default
{
name
:
'errLog'
,
props
:
{
logsList
:
{
type
:
Array
}
},
data
()
{
return
{
dialogTableVisible
:
false
}
}
}
</
script
>
<
style
scoped
>
.bug-svg
{
width
:
1em
;
height
:
1em
;
vertical-align
:
-0.15em
;
fill
:
currentColor
;
overflow
:
hidden
;
width
:
1em
;
height
:
1em
;
vertical-align
:
-0.15em
;
fill
:
currentColor
;
overflow
:
hidden
;
}
</
style
>
src/components/Hamburger/index.vue
View file @
de992c50
<
template
>
<div>
<svg
t=
"1492500959545"
@
click=
"toggleClick"
class=
"wscn-icon hamburger"
:class=
"
{'is-active':isActive}" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1691" xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64">
<path
d=
"M966.8023 568.849776 57.196677 568.849776c-31.397081 0-56.850799-25.452695-56.850799-56.850799l0 0c0-31.397081 25.452695-56.849776 56.850799-56.849776l909.605623 0c31.397081 0 56.849776 25.452695 56.849776 56.849776l0 0C1023.653099 543.397081 998.200404 568.849776 966.8023 568.849776z"
p-id=
"1692"
></path><path
d=
"M966.8023 881.527125 57.196677 881.527125c-31.397081 0-56.850799-25.452695-56.850799-56.849776l0 0c0-31.397081 25.452695-56.849776 56.850799-56.849776l909.605623 0c31.397081 0 56.849776 25.452695 56.849776 56.849776l0 0C1023.653099 856.07443 998.200404 881.527125 966.8023 881.527125z"
p-id=
"1693"
></path><path
d=
"M966.8023 256.17345 57.196677 256.17345c-31.397081 0-56.850799-25.452695-56.850799-56.849776l0 0c0-31.397081 25.452695-56.850799 56.850799-56.850799l909.605623 0c31.397081 0 56.849776 25.452695 56.849776 56.850799l0 0C1023.653099 230.720755 998.200404 256.17345 966.8023 256.17345z"
p-id=
"1694"
></path></svg>
</div>
<div>
<svg
t=
"1492500959545"
@
click=
"toggleClick"
class=
"wscn-icon hamburger"
:class=
"
{'is-active':isActive}" style="" viewBox="0 0 1024 1024"
version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1691" xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64">
<path
d=
"M966.8023 568.849776 57.196677 568.849776c-31.397081 0-56.850799-25.452695-56.850799-56.850799l0 0c0-31.397081 25.452695-56.849776 56.850799-56.849776l909.605623 0c31.397081 0 56.849776 25.452695 56.849776 56.849776l0 0C1023.653099 543.397081 998.200404 568.849776 966.8023 568.849776z"
p-id=
"1692"
></path>
<path
d=
"M966.8023 881.527125 57.196677 881.527125c-31.397081 0-56.850799-25.452695-56.850799-56.849776l0 0c0-31.397081 25.452695-56.849776 56.850799-56.849776l909.605623 0c31.397081 0 56.849776 25.452695 56.849776 56.849776l0 0C1023.653099 856.07443 998.200404 881.527125 966.8023 881.527125z"
p-id=
"1693"
></path>
<path
d=
"M966.8023 256.17345 57.196677 256.17345c-31.397081 0-56.850799-25.452695-56.850799-56.849776l0 0c0-31.397081 25.452695-56.850799 56.850799-56.850799l909.605623 0c31.397081 0 56.849776 25.452695 56.849776 56.850799l0 0C1023.653099 230.720755 998.200404 256.17345 966.8023 256.17345z"
p-id=
"1694"
></path>
</svg>
</div>
</
template
>
<
script
>
export
default
{
name
:
'hamburger'
,
props
:
{
isActive
:
{
type
:
Boolean
,
default
:
false
},
toggleClick
:
{
type
:
Function
,
default
:
null
}
export
default
{
name
:
'hamburger'
,
props
:
{
isActive
:
{
type
:
Boolean
,
default
:
false
},
toggleClick
:
{
type
:
Function
,
default
:
null
}
}
}
</
script
>
<
style
scoped
>
.hamburger
{
display
:
inline-block
;
cursor
:
pointer
;
width
:
20px
;
height
:
20px
;
transform
:
rotate
(
0deg
);
transition
:
.38s
;
transform-origin
:
50%
50%
;
}
.hamburger.is-active
{
transform
:
rotate
(
90deg
);
}
.hamburger
{
display
:
inline-block
;
cursor
:
pointer
;
width
:
20px
;
height
:
20px
;
transform
:
rotate
(
0deg
);
transition
:
.38s
;
transform-origin
:
50%
50%
;
}
.hamburger.is-active
{
transform
:
rotate
(
90deg
);
}
</
style
>
src/components/MDinput/index.vue
View file @
de992c50
<
template
>
<div
class=
"material-input__component"
:class=
"computedClasses"
>
<input
v-if=
"type === 'email'"
type=
"email"
class=
"material-input"
:name=
"name"
:id=
"id"
:placeholder=
"placeholder"
v-model=
"valueCopy"
:readonly=
"readonly"
:disabled=
"disabled"
:autocomplete=
"autocomplete"
:required=
"required"
@
focus=
"handleFocus(true)"
@
blur=
"handleFocus(false)"
@
input=
"handleModelInput"
>
<input
v-if=
"type === 'url'"
type=
"url"
class=
"material-input"
:name=
"name"
:id=
"id"
:placeholder=
"placeholder"
v-model=
"valueCopy"
:readonly=
"readonly"
:disabled=
"disabled"
:autocomplete=
"autocomplete"
:required=
"required"
@
focus=
"handleFocus(true)"
@
blur=
"handleFocus(false)"
@
input=
"handleModelInput"
>
<input
v-if=
"type === 'number'"
type=
"number"
class=
"material-input"
:name=
"name"
:id=
"id"
:placeholder=
"placeholder"
v-model=
"valueCopy"
:readonly=
"readonly"
:disabled=
"disabled"
:autocomplete=
"autocomplete"
:max=
"max"
:min=
"min"
:minlength=
"min
length"
:maxlength=
"maxlength"
:required=
"required"
@
focus=
"handleFocus(true)"
@
blur=
"handleFocus(false)"
@
input=
"handleModelInput"
>
<input
v-if=
"type === 'password'"
type=
"password"
class=
"material-input"
:name=
"name"
:id=
"id"
:placeholder=
"placeholder"
v-model=
"valueCopy"
:readonly=
"readonly"
:disabled=
"disabled"
:autocomplete=
"autocomplete"
:max=
"max"
:min=
"min
"
:required=
"required"
@
focus=
"handleFocus(true)"
@
blur=
"handleFocus(false)"
@
input=
"handleModelInput"
>
<input
v-if=
"type === 'tel'"
type=
"tel"
class=
"material-input"
:name=
"name"
:id=
"id"
:placeholder=
"placeholder"
v-model=
"valueCopy"
:readonly=
"readonly"
:disabled=
"disabled"
:autocomplete=
"autocomplete"
:required=
"required"
@
focus=
"handleFocus(true)"
@
blur=
"handleFocus(false)"
@
input=
"handleModelInput"
>
<input
v-if=
"type === 'text'"
type=
"text"
class=
"material-input"
:name=
"name"
:id=
"id"
:placeholder=
"placeholder"
v-model=
"valueCopy"
:readonly=
"readonly"
:disabled=
"disabled"
:autocomplete=
"autocomplete"
:minlength=
"minlength"
:maxlength=
"maxlength
"
:required=
"required"
@
focus=
"handleFocus(true)"
@
blur=
"handleFocus(false)"
@
input=
"handleModelInput"
>
<div
class=
"material-input__component"
:class=
"computedClasses"
>
<input
v-if=
"type === 'email'"
type=
"email"
class=
"material-input"
:name=
"name"
:id=
"id"
:placeholder=
"placeholder"
v-model=
"valueCopy"
:readonly=
"readonly"
:disabled=
"disabled"
:autocomplete=
"autocomplete"
:required=
"required"
@
focus=
"handleFocus(true)"
@
blur=
"handleFocus(false)"
@
input=
"handleModelInput"
>
<input
v-if=
"type === 'url'"
type=
"url"
class=
"material-input"
:name=
"name"
:id=
"id"
:placeholder=
"placeholder"
v-model=
"valueCopy"
:readonly=
"readonly"
:disabled=
"disabled"
:autocomplete=
"autocomplete"
:required=
"required"
@
focus=
"handleFocus(true)"
@
blur=
"handleFocus(false)"
@
input=
"handleModelInput"
>
<input
v-if=
"type === 'number'"
type=
"number"
class=
"material-input"
:name=
"name"
:id=
"id"
:placeholder=
"placeholder"
v-model=
"valueCopy"
:readonly=
"readonly"
:disabled=
"disabled"
:autocomplete=
"autocomplete"
:max=
"max"
:min=
"min"
:minlength=
"minlength"
:maxlength=
"max
length"
:required=
"required"
@
focus=
"handleFocus(true)"
@
blur=
"handleFocus(false)"
@
input=
"handleModelInput"
>
<input
v-if=
"type === 'password'"
type=
"password"
class=
"material-input"
:name=
"name"
:id=
"id"
:placeholder=
"placeholder"
v-model=
"valueCopy"
:readonly=
"readonly"
:disabled=
"disabled"
:autocomplete=
"autocomplete"
:max=
"max"
:min=
"min"
:required=
"required
"
@
focus=
"handleFocus(true)"
@
blur=
"handleFocus(false)"
@
input=
"handleModelInput"
>
<input
v-if=
"type === 'tel'"
type=
"tel"
class=
"material-input"
:name=
"name"
:id=
"id"
:placeholder=
"placeholder"
v-model=
"valueCopy"
:readonly=
"readonly"
:disabled=
"disabled"
:autocomplete=
"autocomplete"
:required=
"required"
@
focus=
"handleFocus(true)"
@
blur=
"handleFocus(false)"
@
input=
"handleModelInput"
>
<input
v-if=
"type === 'text'"
type=
"text"
class=
"material-input"
:name=
"name"
:id=
"id"
:placeholder=
"placeholder"
v-model=
"valueCopy"
:readonly=
"readonly"
:disabled=
"disabled"
:autocomplete=
"autocomplete"
:minlength=
"minlength"
:maxlength=
"maxlength"
:required=
"required
"
@
focus=
"handleFocus(true)"
@
blur=
"handleFocus(false)"
@
input=
"handleModelInput"
>
<span
class=
"material-input-bar"
></span>
<span
class=
"material-input-bar"
></span>
<label
class=
"material-label"
>
<label
class=
"material-label"
>
<slot></slot>
</label>
<div
v-if=
"errorMessages"
class=
"material-errors"
>
<div
v-for=
"error in computedErrors"
class=
"material-error"
>
{{
error
}}
</div>
</div>
</div>
<div
v-if=
"errorMessages"
class=
"material-errors"
>
<div
v-for=
"error in computedErrors"
class=
"material-error"
:key=
'error'
>
{{
error
}}
</div>
</div>
</div>
</
template
>
<
script
>
// source:https://github.com/wemake-services/vue-material-input/blob/master/src/components/MaterialInput.vue
export
default
{
name
:
'material-input'
,
computed
:
{
computedErrors
()
{
return
typeof
this
.
errorMessages
===
'string'
// source:https://github.com/wemake-services/vue-material-input/blob/master/src/components/MaterialInput.vue
export
default
{
name
:
'material-input'
,
computed
:
{
computedErrors
()
{
return
typeof
this
.
errorMessages
===
'string'
?
[
this
.
errorMessages
]
:
this
.
errorMessages
},
computedClasses
()
{
return
{
'material--active'
:
this
.
focus
,
'material--disabled'
:
this
.
disabled
,
'material--has-errors'
:
Boolean
(
!
this
.
valid
||
(
this
.
errorMessages
&&
this
.
errorMessages
.
length
)),
'material--raised'
:
Boolean
(
this
.
focus
||
this
.
valueCopy
||
// has value
},
computedClasses
()
{
return
{
'material--active'
:
this
.
focus
,
'material--disabled'
:
this
.
disabled
,
'material--has-errors'
:
Boolean
(
!
this
.
valid
||
(
this
.
errorMessages
&&
this
.
errorMessages
.
length
)),
'material--raised'
:
Boolean
(
this
.
focus
||
this
.
valueCopy
||
// has value
(
this
.
placeholder
&&
!
this
.
valueCopy
))
// has placeholder
}
}
},
data
()
{
return
{
valueCopy
:
null
,
focus
:
false
,
valid
:
true
}
},
beforeMount
()
{
}
}
},
data
()
{
return
{
valueCopy
:
null
,
focus
:
false
,
valid
:
true
}
},
beforeMount
()
{
// Here we are following the Vue2 convention on custom v-model:
// https://github.com/vuejs/vue/issues/2873#issuecomment-223759341
this
.
copyValue
(
this
.
value
)
},
methods
:
{
handleModelInput
(
event
)
{
this
.
$emit
(
'input'
,
event
.
target
.
value
,
event
)
this
.
handleValidation
()
},
handleFocus
(
focused
)
{
this
.
focus
=
focused
},
handleValidation
()
{
this
.
valid
=
this
.
$el
?
this
.
$el
.
querySelector
(
'.material-input'
).
validity
.
valid
:
this
.
valid
},
copyValue
(
value
)
{
this
.
valueCopy
=
value
this
.
handleValidation
()
}
},
watch
:
{
value
(
newValue
)
{
this
.
copyValue
(
newValue
)
}
},
props
:
{
id
:
{
type
:
String
,
default
:
null
},
name
:
{
type
:
String
,
default
:
null
},
type
:
{
type
:
String
,
default
:
'text'
},
value
:
{
default
:
null
},
placeholder
:
{
type
:
String
,
default
:
null
},
readonly
:
{
type
:
Boolean
,
default
:
false
},
disabled
:
{
type
:
Boolean
,
default
:
false
},
min
:
{
type
:
String
,
default
:
null
},
max
:
{
type
:
String
,
default
:
null
},
minlength
:
{
type
:
Number
,
default
:
null
},
maxlength
:
{
type
:
Number
,
default
:
null
},
required
:
{
type
:
Boolean
,
default
:
true
},
autocomplete
:
{
type
:
String
,
default
:
'off'
},
errorMessages
:
{
type
:
[
Array
,
String
],
default
:
null
}
}
this
.
copyValue
(
this
.
value
)
},
methods
:
{
handleModelInput
(
event
)
{
this
.
$emit
(
'input'
,
event
.
target
.
value
,
event
)
this
.
handleValidation
()
},
handleFocus
(
focused
)
{
this
.
focus
=
focused
},
handleValidation
()
{
this
.
valid
=
this
.
$el
?
this
.
$el
.
querySelector
(
'.material-input'
).
validity
.
valid
:
this
.
valid
},
copyValue
(
value
)
{
this
.
valueCopy
=
value
this
.
handleValidation
()
}
},
watch
:
{
value
(
newValue
)
{
this
.
copyValue
(
newValue
)
}
},
props
:
{
id
:
{
type
:
String
,
default
:
null
},
name
:
{
type
:
String
,
default
:
null
},
type
:
{
type
:
String
,
default
:
'text'
},
value
:
{
default
:
null
},
placeholder
:
{
type
:
String
,
default
:
null
},
readonly
:
{
type
:
Boolean
,
default
:
false
},
disabled
:
{
type
:
Boolean
,
default
:
false
},
min
:
{
type
:
String
,
default
:
null
},
max
:
{
type
:
String
,
default
:
null
},
minlength
:
{
type
:
Number
,
default
:
null
},
maxlength
:
{
type
:
Number
,
default
:
null
},
required
:
{
type
:
Boolean
,
default
:
true
},
autocomplete
:
{
type
:
String
,
default
:
'off'
},
errorMessages
:
{
type
:
[
Array
,
String
],
default
:
null
}
}
}
</
script
>
<
style
rel=
"stylesheet/scss"
lang=
"scss"
scoped
>
...
...
src/components/MdEditor/index.vue
View file @
de992c50
...
...
@@ -6,106 +6,109 @@
</
template
>
<
script
>
import
'simplemde/dist/simplemde.min.css'
import
SimpleMDE
from
'simplemde'
export
default
{
name
:
'Sticky'
,
props
:
{
value
:
String
,
id
:
{
type
:
String
,
default
:
'markdown-editor'
},
autofocus
:
{
type
:
Boolean
,
default
:
false
},
placeholder
:
{
type
:
String
,
default
:
''
import
'simplemde/dist/simplemde.min.css'
;
import
SimpleMDE
from
'simplemde'
;
export
default
{
name
:
'Sticky'
,
props
:
{
value
:
String
,
id
:
{
type
:
String
,
default
:
'markdown-editor'
},
autofocus
:
{
type
:
Boolean
,
default
:
false
},
placeholder
:
{
type
:
String
,
default
:
''
},
height
:
{
type
:
Number
,
default
:
150
},
zIndex
:
{
type
:
Number
,
default
:
10
},
toolbar
:
{
type
:
Array
}
},
height
:
{
type
:
Number
,
default
:
150
data
()
{
return
{
simplemde
:
null
,
hasChange
:
false
};
},
zIndex
:
{
type
:
Number
,
default
:
10
watch
:
{
value
(
val
)
{
if
(
val
===
this
.
simplemde
.
value
()
&&
!
this
.
hasChange
)
return
;
this
.
simplemde
.
value
(
val
);
}
},
toolbar
:
{
type
:
Array
}
},
data
()
{
return
{
simplemde
:
null
,
hasChange
:
false
};
},
watch
:
{
value
(
val
)
{
if
(
val
===
this
.
simplemde
.
value
()
&&
!
this
.
hasChange
)
return
;
this
.
simplemde
.
value
(
val
);
}
},
mounted
()
{
this
.
simplemde
=
new
SimpleMDE
({
element
:
document
.
getElementById
(
this
.
id
),
autofocus
:
this
.
autofocus
,
toolbar
:
this
.
toolbar
,
spellChecker
:
false
,
insertTexts
:
{
link
:
[
'['
,
']( )'
]
},
mounted
()
{
this
.
simplemde
=
new
SimpleMDE
({
element
:
document
.
getElementById
(
this
.
id
),
autofocus
:
this
.
autofocus
,
toolbar
:
this
.
toolbar
,
spellChecker
:
false
,
insertTexts
:
{
link
:
[
'['
,
']( )'
]
},
// hideIcons: ['guide', 'heading', 'quote', 'image', 'preview', 'side-by-side', 'fullscreen'],
placeholder
:
this
.
placeholder
});
if
(
this
.
value
)
{
this
.
simplemde
.
value
(
this
.
value
);
}
this
.
simplemde
.
codemirror
.
on
(
'change'
,
()
=>
{
if
(
this
.
hasChange
)
{
this
.
hasChange
=
true
placeholder
:
this
.
placeholder
});
if
(
this
.
value
)
{
this
.
simplemde
.
value
(
this
.
value
);
}
this
.
$emit
(
'input'
,
this
.
simplemde
.
value
());
});
},
destroyed
()
{
this
.
simplemde
=
null
;
}
this
.
simplemde
.
codemirror
.
on
(
'change'
,
()
=>
{
if
(
this
.
hasChange
)
{
this
.
hasChange
=
true
}
this
.
$emit
(
'input'
,
this
.
simplemde
.
value
());
});
},
destroyed
()
{
this
.
simplemde
=
null
;
}
};
</
script
>
<
style
>
.simplemde-container
.CodeMirror
{
/*height: 150px;*/
min-height
:
150px
;
}
.simplemde-container
.CodeMirror-scroll
{
min-height
:
150px
;
}
.simplemde-container
.CodeMirror
{
/*height: 150px;*/
min-height
:
150px
;
}
.simplemde-container
.CodeMirror-scroll
{
min-height
:
150px
;
}
.simplemde-container
.CodeMirror-code
{
padding-bottom
:
40px
;
}
.simplemde-container
.CodeMirror-code
{
padding-bottom
:
40px
;
}
.simplemde-container
.editor-statusbar
{
display
:
none
;
}
.simplemde-container
.editor-statusbar
{
display
:
none
;
}
.simplemde-container
.CodeMirror
.CodeMirror-code
.cm-link
{
color
:
#1482F0
;
}
.simplemde-container
.CodeMirror
.CodeMirror-code
.cm-link
{
color
:
#1482F0
;
}
.simplemde-container
.CodeMirror
.CodeMirror-code
.cm-string.cm-url
{
color
:
#2d3b4d
;
font-weight
:
bold
;
}
.simplemde-container
.CodeMirror
.CodeMirror-code
.cm-string.cm-url
{
color
:
#2d3b4d
;
font-weight
:
bold
;
}
.simplemde-container
.CodeMirror
.CodeMirror-code
.cm-formatting-link-string.cm-url
{
padding
:
0
2px
;
font-weight
:
bold
;
color
:
#E61E1E
;
}
.simplemde-container
.CodeMirror
.CodeMirror-code
.cm-formatting-link-string.cm-url
{
padding
:
0
2px
;
font-weight
:
bold
;
color
:
#E61E1E
;
}
</
style
>
src/components/PanThumb/index.vue
View file @
de992c50
<
template
>
<div
class=
"pan-item"
:style=
"
{zIndex:zIndex,height:height,width:width}">
<div
class=
"pan-info"
>
<div
class=
"pan-info-roles-container"
>
<slot></slot>
</div>
</div>
<img
class=
"pan-thumb"
:src=
"image"
>
</div>
<div
class=
"pan-item"
:style=
"
{zIndex:zIndex,height:height,width:width}">
<div
class=
"pan-info"
>
<div
class=
"pan-info-roles-container"
>
<slot></slot>
</div>
</div>
<img
class=
"pan-thumb"
:src=
"image"
>
</div>
</
template
>
<
script
>
export
default
{
name
:
'PanThumb'
,
props
:
{
image
:
{
type
:
String
,
required
:
true
},
zIndex
:
{
type
:
Number
,
default
:
100
},
width
:
{
type
:
String
,
default
:
'150px'
},
height
:
{
type
:
String
,
default
:
'150px'
}
export
default
{
name
:
'PanThumb'
,
props
:
{
image
:
{
type
:
String
,
required
:
true
},
zIndex
:
{
type
:
Number
,
default
:
100
},
data
()
{
return
{};
width
:
{
type
:
String
,
default
:
'150px'
},
height
:
{
type
:
String
,
default
:
'150px'
}
};
}
};
</
script
>
<
style
scoped
>
.pan-item
{
width
:
200px
;
height
:
200px
;
border-radius
:
50%
;
display
:
inline-block
;
position
:
relative
;
cursor
:
default
;
box-shadow
:
0
1px
3px
rgba
(
0
,
0
,
0
,
0.2
);
}
.pan-item
{
width
:
200px
;
height
:
200px
;
border-radius
:
50%
;
display
:
inline-block
;
position
:
relative
;
cursor
:
default
;
box-shadow
:
0
1px
3px
rgba
(
0
,
0
,
0
,
0.2
);
}
.pan-info-roles-container
{
padding
:
20px
;
text-align
:
center
;
}
.pan-info-roles-container
{
padding
:
20px
;
text-align
:
center
;
}
.pan-thumb
{
width
:
100%
;
height
:
100%
;
background-size
:
100%
;
border-radius
:
50%
;
overflow
:
hidden
;
position
:
absolute
;
transform-origin
:
95%
40%
;
transition
:
all
0.3s
ease-in-out
;
}
.pan-thumb
{
width
:
100%
;
height
:
100%
;
background-size
:
100%
;
border-radius
:
50%
;
overflow
:
hidden
;
position
:
absolute
;
transform-origin
:
95%
40%
;
transition
:
all
0.3s
ease-in-out
;
}
.pan-thumb
:after
{
content
:
''
;
width
:
8px
;
height
:
8px
;
position
:
absolute
;
border-radius
:
50%
;
top
:
40%
;
left
:
95%
;
margin
:
-4px
0
0
-4px
;
background
:
radial-gradient
(
ellipse
at
center
,
rgba
(
14
,
14
,
14
,
1
)
0%
,
rgba
(
125
,
126
,
125
,
1
)
100%
);
box-shadow
:
0
0
1px
rgba
(
255
,
255
,
255
,
0.9
);
}
.pan-thumb
:after
{
content
:
''
;
width
:
8px
;
height
:
8px
;
position
:
absolute
;
border-radius
:
50%
;
top
:
40%
;
left
:
95%
;
margin
:
-4px
0
0
-4px
;
background
:
radial-gradient
(
ellipse
at
center
,
rgba
(
14
,
14
,
14
,
1
)
0%
,
rgba
(
125
,
126
,
125
,
1
)
100%
);
box-shadow
:
0
0
1px
rgba
(
255
,
255
,
255
,
0.9
);
}
.pan-info
{
position
:
absolute
;
width
:
inherit
;
height
:
inherit
;
border-radius
:
50%
;
overflow
:
hidden
;
box-shadow
:
inset
0
0
0
5px
rgba
(
0
,
0
,
0
,
0.05
);
}
.pan-info
{
position
:
absolute
;
width
:
inherit
;
height
:
inherit
;
border-radius
:
50%
;
overflow
:
hidden
;
box-shadow
:
inset
0
0
0
5px
rgba
(
0
,
0
,
0
,
0.05
);
}
.pan-info
h3
{
color
:
#fff
;
text-transform
:
uppercase
;
position
:
relative
;
letter-spacing
:
2px
;
font-size
:
18px
;
margin
:
0
60px
;
padding
:
22px
0
0
0
;
height
:
85px
;
font-family
:
'Open Sans'
,
Arial
,
sans-serif
;
text-shadow
:
0
0
1px
#fff
,
0
1px
2px
rgba
(
0
,
0
,
0
,
0.3
);
}
.pan-info
h3
{
color
:
#fff
;
text-transform
:
uppercase
;
position
:
relative
;
letter-spacing
:
2px
;
font-size
:
18px
;
margin
:
0
60px
;
padding
:
22px
0
0
0
;
height
:
85px
;
font-family
:
'Open Sans'
,
Arial
,
sans-serif
;
text-shadow
:
0
0
1px
#fff
,
0
1px
2px
rgba
(
0
,
0
,
0
,
0.3
);
}
.pan-info
p
{
color
:
#fff
;
padding
:
10px
5px
;
font-style
:
italic
;
margin
:
0
30px
;
font-size
:
12px
;
border-top
:
1px
solid
rgba
(
255
,
255
,
255
,
0.5
);
}
.pan-info
p
{
color
:
#fff
;
padding
:
10px
5px
;
font-style
:
italic
;
margin
:
0
30px
;
font-size
:
12px
;
border-top
:
1px
solid
rgba
(
255
,
255
,
255
,
0.5
);
}
.pan-info
p
a
{
display
:
block
;
color
:
#333
;
width
:
80px
;
height
:
80px
;
background
:
rgba
(
255
,
255
,
255
,
0.3
);
border-radius
:
50%
;
color
:
#fff
;
font-style
:
normal
;
font-weight
:
700
;
text-transform
:
uppercase
;
font-size
:
9px
;
letter-spacing
:
1px
;
padding-top
:
24px
;
margin
:
7px
auto
0
;
font-family
:
'Open Sans'
,
Arial
,
sans-serif
;
opacity
:
0
;
transition
:
transform
0.3s
ease-in-out
0.2s
,
opacity
0.3s
ease-in-out
0.2s
,
background
0.2s
linear
0s
;
transform
:
translateX
(
60px
)
rotate
(
90deg
);
}
.pan-info
p
a
{
display
:
block
;
color
:
#333
;
width
:
80px
;
height
:
80px
;
background
:
rgba
(
255
,
255
,
255
,
0.3
);
border-radius
:
50%
;
color
:
#fff
;
font-style
:
normal
;
font-weight
:
700
;
text-transform
:
uppercase
;
font-size
:
9px
;
letter-spacing
:
1px
;
padding-top
:
24px
;
margin
:
7px
auto
0
;
font-family
:
'Open Sans'
,
Arial
,
sans-serif
;
opacity
:
0
;
transition
:
transform
0.3s
ease-in-out
0.2s
,
opacity
0.3s
ease-in-out
0.2s
,
background
0.2s
linear
0s
;
transform
:
translateX
(
60px
)
rotate
(
90deg
);
}
.pan-info
p
a
:hover
{
background
:
rgba
(
255
,
255
,
255
,
0.5
);
}
.pan-info
p
a
:hover
{
background
:
rgba
(
255
,
255
,
255
,
0.5
);
}
.pan-item
:hover
.pan-thumb
{
transform
:
rotate
(
-110deg
);
}
.pan-item
:hover
.pan-thumb
{
transform
:
rotate
(
-110deg
);
}
.pan-item
:hover
.pan-info
p
a
{
opacity
:
1
;
transform
:
translateX
(
0px
)
rotate
(
0deg
);
}
.pan-item
:hover
.pan-info
p
a
{
opacity
:
1
;
transform
:
translateX
(
0px
)
rotate
(
0deg
);
}
</
style
>
src/components/Screenfull/index.vue
View file @
de992c50
<
template
>
<svg
@
click=
'click'
class=
"icon screenfull"
xmlns=
"http://www.w3.org/2000/svg"
xmlns:xlink=
"http://www.w3.org/1999/xlink"
t=
"1497503607356"
viewBox=
"0 0 1024 1024"
version=
"1.1"
p-id=
"4109"
:fill=
'fill'
:width=
"width"
:height=
"height"
><path
d=
"M604.157933 512l204.484208 204.484208 82.942037-82.942037c10.364045-10.952446 26.498514-13.83817 40.309054-8.067746 13.249769 5.742794 22.465664 18.99154 22.465664 33.977859l0 258.042008c0 20.168342-16.695241 36.863582-36.863582 36.863582L659.452283 954.357873c-14.986319 0-28.236088-9.215896-33.977859-23.025413-5.770424-13.249769-2.885723-29.384237 8.067746-39.748283l82.942037-82.942037L512 604.157933 307.515792 808.642141l82.942037 82.942037c10.952446 10.364045 13.83817 26.498514 8.067746 39.748283-5.742794 13.809517-18.99154 23.025413-33.977859 23.025413L106.504686 954.357873c-20.168342 0-36.863582-16.695241-36.863582-36.863582L69.641103 659.452283c0-14.986319 9.215896-28.236088 23.025413-33.977859 13.249769-5.770424 29.384237-2.8847 39.748283 8.067746l82.942037 82.942037 204.484208-204.484208L215.357859 307.515792l-82.942037 82.942037c-6.890944 6.918573-16.10684 10.952446-25.911136 10.952446-4.593622 0-9.804297-1.14815-13.83817-2.8847-13.809517-5.742794-23.025413-18.99154-23.025413-33.977859L69.641103 106.504686c0-20.168342 16.695241-36.863582 36.863582-36.863582L364.546693 69.641103c14.986319 0 28.236088 9.215896 33.977859 23.025413 5.770424 13.249769 2.8847 29.384237-8.067746 39.748283l-82.942037 82.942037 204.484208 204.484208L716.484208 215.357859l-82.942037-82.942037c-10.952446-10.364045-13.83817-26.498514-8.067746-39.748283 5.742794-13.809517 18.99154-23.025413 33.977859-23.025413l258.042008 0c20.168342 0 36.863582 16.695241 36.863582 36.863582l0 258.042008c0 14.986319-9.215896 28.236088-22.465664 33.977859-4.593622 1.736551-9.804297 2.8847-14.397918 2.8847-9.804297 0-19.020192-4.033873-25.911136-10.952446l-82.942037-82.942037L604.157933 512z"
p-id=
"4110"
/></svg>
<svg
@
click=
'click'
class=
"icon screenfull"
xmlns=
"http://www.w3.org/2000/svg"
xmlns:xlink=
"http://www.w3.org/1999/xlink"
t=
"1497503607356"
viewBox=
"0 0 1024 1024"
version=
"1.1"
p-id=
"4109"
:fill=
'fill'
:width=
"width"
:height=
"height"
>
<path
d=
"M604.157933 512l204.484208 204.484208 82.942037-82.942037c10.364045-10.952446 26.498514-13.83817 40.309054-8.067746 13.249769 5.742794 22.465664 18.99154 22.465664 33.977859l0 258.042008c0 20.168342-16.695241 36.863582-36.863582 36.863582L659.452283 954.357873c-14.986319 0-28.236088-9.215896-33.977859-23.025413-5.770424-13.249769-2.885723-29.384237 8.067746-39.748283l82.942037-82.942037L512 604.157933 307.515792 808.642141l82.942037 82.942037c10.952446 10.364045 13.83817 26.498514 8.067746 39.748283-5.742794 13.809517-18.99154 23.025413-33.977859 23.025413L106.504686 954.357873c-20.168342 0-36.863582-16.695241-36.863582-36.863582L69.641103 659.452283c0-14.986319 9.215896-28.236088 23.025413-33.977859 13.249769-5.770424 29.384237-2.8847 39.748283 8.067746l82.942037 82.942037 204.484208-204.484208L215.357859 307.515792l-82.942037 82.942037c-6.890944 6.918573-16.10684 10.952446-25.911136 10.952446-4.593622 0-9.804297-1.14815-13.83817-2.8847-13.809517-5.742794-23.025413-18.99154-23.025413-33.977859L69.641103 106.504686c0-20.168342 16.695241-36.863582 36.863582-36.863582L364.546693 69.641103c14.986319 0 28.236088 9.215896 33.977859 23.025413 5.770424 13.249769 2.8847 29.384237-8.067746 39.748283l-82.942037 82.942037 204.484208 204.484208L716.484208 215.357859l-82.942037-82.942037c-10.952446-10.364045-13.83817-26.498514-8.067746-39.748283 5.742794-13.809517 18.99154-23.025413 33.977859-23.025413l258.042008 0c20.168342 0 36.863582 16.695241 36.863582 36.863582l0 258.042008c0 14.986319-9.215896 28.236088-22.465664 33.977859-4.593622 1.736551-9.804297 2.8847-14.397918 2.8847-9.804297 0-19.020192-4.033873-25.911136-10.952446l-82.942037-82.942037L604.157933 512z"
p-id=
"4110"
/>
</svg>
</
template
>
<
script
>
import
screenfull
from
'screenfull'
;
export
default
{
name
:
'hamburger'
,
props
:
{
width
:
{
type
:
Number
,
default
:
22
},
height
:
{
type
:
Number
,
default
:
22
},
fill
:
{
type
:
String
,
default
:
'#48576a'
}
import
screenfull
from
'screenfull'
;
export
default
{
name
:
'hamburger'
,
props
:
{
width
:
{
type
:
Number
,
default
:
22
},
data
()
{
return
{
isFullscreen
:
false
}
height
:
{
type
:
Number
,
default
:
22
},
methods
:
{
click
()
{
if
(
!
screenfull
.
enabled
)
{
this
.
$message
({
message
:
'you browser can not work'
,
type
:
'warning'
});
return
false
;
}
screenfull
.
toggle
();
fill
:
{
type
:
String
,
default
:
'#48576a'
}
},
data
()
{
return
{
isFullscreen
:
false
}
},
methods
:
{
click
()
{
if
(
!
screenfull
.
enabled
)
{
this
.
$message
({
message
:
'you browser can not work'
,
type
:
'warning'
});
return
false
;
}
screenfull
.
toggle
();
}
}
}
</
script
>
<
style
scoped
>
.screenfull
{
display
:
inline-block
;
cursor
:
pointer
;
vertical-align
:
-0.15em
;
}
.screenfull
{
display
:
inline-block
;
cursor
:
pointer
;
vertical-align
:
-0.15em
;
}
</
style
>
src/components/SplitPane/Pane.vue
View file @
de992c50
<
template
>
<div
:class=
"classes"
>
<slot></slot>
</div>
<div
:class=
"classes"
>
<slot></slot>
</div>
</
template
>
<
script
>
export
default
{
name
:
'Pane'
,
data
()
{
const
classes
=
[
'Pane'
,
this
.
$parent
.
split
,
'className'
];
return
{
classes
:
classes
.
join
(
' '
),
percent
:
50
}
}
export
default
{
name
:
'Pane'
,
data
()
{
const
classes
=
[
'Pane'
,
this
.
$parent
.
split
,
'className'
];
return
{
classes
:
classes
.
join
(
' '
),
percent
:
50
}
}
}
</
script
>
<
style
>
.splitter-pane.vertical.splitter-paneL
{
position
:
absolute
;
left
:
0px
;
height
:
100%
;
}
.splitter-pane.vertical.splitter-paneR
{
position
:
absolute
;
right
:
0px
;
height
:
100%
;
}
.splitter-pane.horizontal.splitter-paneL
{
position
:
absolute
;
top
:
0px
;
width
:
100%
;
}
.splitter-pane.horizontal.splitter-paneR
{
position
:
absolute
;
bottom
:
0px
;
width
:
100%
;
}
<
style
scoped
>
.splitter-pane.vertical.splitter-paneL
{
position
:
absolute
;
left
:
0px
;
height
:
100%
;
}
.splitter-pane.vertical.splitter-paneR
{
position
:
absolute
;
right
:
0px
;
height
:
100%
;
}
.splitter-pane.horizontal.splitter-paneL
{
position
:
absolute
;
top
:
0px
;
width
:
100%
;
}
.splitter-pane.horizontal.splitter-paneR
{
position
:
absolute
;
bottom
:
0px
;
width
:
100%
;
}
</
style
>
src/components/SplitPane/Resizer.vue
View file @
de992c50
<
template
>
<div
:class=
"classes"
@
mousedown=
"onMouseDown"
></div>
<div
:class=
"classes"
@
mousedown=
"onMouseDown"
></div>
</
template
>
<
script
>
export
default
{
props
:
{
split
:
{
validator
(
value
)
{
return
[
'vertical'
,
'horizontal'
].
indexOf
(
value
)
>=
0
},
required
:
true
export
default
{
props
:
{
split
:
{
validator
(
value
)
{
return
[
'vertical'
,
'horizontal'
].
indexOf
(
value
)
>=
0
},
onMouseDown
:
{
type
:
Function
,
required
:
true
}
required
:
true
},
data
()
{
const
classes
=
[
'Resizer'
,
this
.
split
,
'className'
];
return
{
classes
:
classes
.
join
(
' '
)
}
onMouseDown
:
{
type
:
Function
,
required
:
true
}
},
data
()
{
const
classes
=
[
'Resizer'
,
this
.
split
,
'className'
];
return
{
classes
:
classes
.
join
(
' '
)
}
}
}
</
script
>
<
style
scoped
>
.Resizer
{
-moz-box-sizing
:
border-box
;
-webkit-box-sizing
:
border-box
;
box-sizing
:
border-box
;
background
:
#000
;
position
:
absolute
;
opacity
:
.2
;
z-index
:
1
;
/*-moz-background-clip: padding;*/
/*-webkit-background-clip: padding;*/
/*background-clip: padding-box;*/
}
.Resizer
{
-moz-box-sizing
:
border-box
;
-webkit-box-sizing
:
border-box
;
box-sizing
:
border-box
;
background
:
#000
;
position
:
absolute
;
opacity
:
.2
;
z-index
:
1
;
/*-moz-background-clip: padding;*/
/*-webkit-background-clip: padding;*/
/*background-clip: padding-box;*/
}
/*.Resizer:hover {*/
/*-webkit-transition: all 2s ease;*/
/*transition: all 2s ease;*/
/*}*/
/*.Resizer:hover {*/
/*-webkit-transition: all 2s ease;*/
/*transition: all 2s ease;*/
/*}*/
.Resizer.horizontal
{
height
:
11px
;
margin
:
-5px
0
;
border-top
:
5px
solid
rgba
(
255
,
255
,
255
,
0
);
border-bottom
:
5px
solid
rgba
(
255
,
255
,
255
,
0
);
cursor
:
row-resize
;
width
:
100%
;
}
.Resizer.horizontal
{
height
:
11px
;
margin
:
-5px
0
;
border-top
:
5px
solid
rgba
(
255
,
255
,
255
,
0
);
border-bottom
:
5px
solid
rgba
(
255
,
255
,
255
,
0
);
cursor
:
row-resize
;
width
:
100%
;
}
.Resizer.horizontal
:hover
{
border-top
:
5px
solid
rgba
(
0
,
0
,
0
,
0.5
);
border-bottom
:
5px
solid
rgba
(
0
,
0
,
0
,
0.5
);
}
.Resizer.horizontal
:hover
{
border-top
:
5px
solid
rgba
(
0
,
0
,
0
,
0.5
);
border-bottom
:
5px
solid
rgba
(
0
,
0
,
0
,
0.5
);
}
.Resizer.vertical
{
width
:
11px
;
height
:
100%
;
border-left
:
5px
solid
rgba
(
255
,
255
,
255
,
0
);
border-right
:
5px
solid
rgba
(
255
,
255
,
255
,
0
);
cursor
:
col-resize
;
}
.Resizer.vertical
{
width
:
11px
;
height
:
100%
;
border-left
:
5px
solid
rgba
(
255
,
255
,
255
,
0
);
border-right
:
5px
solid
rgba
(
255
,
255
,
255
,
0
);
cursor
:
col-resize
;
}
.Resizer.vertical
:hover
{
border-left
:
5px
solid
rgba
(
0
,
0
,
0
,
0.5
);
border-right
:
5px
solid
rgba
(
0
,
0
,
0
,
0.5
);
}
.Resizer.vertical
:hover
{
border-left
:
5px
solid
rgba
(
0
,
0
,
0
,
0.5
);
border-right
:
5px
solid
rgba
(
0
,
0
,
0
,
0.5
);
}
</
style
>
src/components/SplitPane/index.vue
View file @
de992c50
<
template
>
<div
ref
:style=
"
{ cursor, userSelect}" class="vue-splitter-container clearfix" @mouseup="onMouseUp"
@mousemove="onMouseMove">
<Pane
class=
"splitter-pane splitter-paneL"
:split=
"split"
:style=
"
{ [type]: percent+'%'}">
<slot
name=
"paneL"
></slot>
</Pane>
<Resizer
:style=
"
{ [resizeType]: percent+'%'}" :split="split" :onMouseDown="onMouseDown"
@click="onClick">
</Resizer>
<Pane
class=
"splitter-pane splitter-paneR"
:split=
"split"
:style=
"
{ [type]: 100-percent+'%'}">
<slot
name=
"paneR"
></slot>
</Pane>
</div>
<div
ref
:style=
"
{ cursor, userSelect}" class="vue-splitter-container clearfix" @mouseup="onMouseUp" @mousemove="onMouseMove">
<pane
class=
"splitter-pane splitter-paneL"
:split=
"split"
:style=
"
{ [type]: percent+'%'}">
<slot
name=
"paneL"
></slot>
</pane>
<resizer
:style=
"
{ [resizeType]: percent+'%'}" :split="split" :onMouseDown="onMouseDown" @click="onClick">
</resizer>
<pane
class=
"splitter-pane splitter-paneR"
:split=
"split"
:style=
"
{ [type]: 100-percent+'%'}">
<slot
name=
"paneR"
></slot>
</pane>
</div>
</
template
>
<
style
scoped
>
.clearfix
:after
{
visibility
:
hidden
;
display
:
block
;
font-size
:
0
;
content
:
" "
;
clear
:
both
;
height
:
0
;
}
.vue-splitter-container
{
height
:
100%
;
/*display: flex;*/
position
:
relative
;
}
</
style
>
<
script
>
import
Resizer
from
'./Resizer'
;
import
Pane
from
'./Pane'
;
export
default
{
name
:
'splitPane'
,
components
:
{
Resizer
,
Pane
},
props
:
{
margin
:
{
type
:
Number
,
default
:
10
import
Resizer
from
'./Resizer'
;
import
Pane
from
'./Pane'
;
export
default
{
name
:
'splitPane'
,
components
:
{
Resizer
,
Pane
},
props
:
{
margin
:
{
type
:
Number
,
default
:
10
},
split
:
{
validator
(
value
)
{
return
[
'vertical'
,
'horizontal'
].
indexOf
(
value
)
>=
0
},
split
:
{
validator
(
value
)
{
return
[
'vertical'
,
'horizontal'
].
indexOf
(
value
)
>=
0
},
required
:
true
}
required
:
true
}
},
data
()
{
return
{
active
:
false
,
hasMoved
:
false
,
height
:
null
,
percent
:
50
,
type
:
this
.
split
===
'vertical'
?
'width'
:
'height'
,
resizeType
:
this
.
split
===
'vertical'
?
'left'
:
'top'
}
},
computed
:
{
userSelect
()
{
return
this
.
active
?
'none'
:
''
},
data
()
{
return
{
active
:
false
,
hasMoved
:
false
,
height
:
null
,
percent
:
50
,
type
:
this
.
split
===
'vertical'
?
'width'
:
'height'
,
resizeType
:
this
.
split
===
'vertical'
?
'left'
:
'top'
cursor
()
{
return
this
.
active
?
'col-resize'
:
''
}
},
methods
:
{
onClick
()
{
if
(
!
this
.
hasMoved
)
{
this
.
percent
=
50
;
this
.
$emit
(
'resize'
);
}
},
computed
:
{
userSelect
()
{
return
this
.
active
?
'none'
:
''
},
cursor
()
{
return
this
.
active
?
'col-resize'
:
''
}
onMouseDown
()
{
this
.
active
=
true
;
this
.
hasMoved
=
false
;
},
methods
:
{
onClick
()
{
if
(
!
this
.
hasMoved
)
{
this
.
percent
=
50
;
this
.
$emit
(
'resize'
);
}
},
onMouseDown
()
{
this
.
active
=
true
;
this
.
hasMoved
=
false
;
},
onMouseUp
()
{
onMouseUp
()
{
this
.
active
=
false
;
},
onMouseMove
(
e
)
{
if
(
e
.
buttons
===
0
||
e
.
which
===
0
)
{
this
.
active
=
false
;
},
onMouseMove
(
e
)
{
if
(
e
.
buttons
===
0
||
e
.
which
===
0
)
{
this
.
active
=
false
;
}
if
(
this
.
active
)
{
let
offset
=
0
;
let
target
=
e
.
currentTarget
;
if
(
this
.
split
===
'vertical'
)
{
while
(
target
)
{
offset
+=
target
.
offsetLeft
;
target
=
target
.
offsetParent
;
}
}
else
{
while
(
target
)
{
offset
+=
target
.
offsetTop
;
target
=
target
.
offsetParent
;
}
}
if
(
this
.
active
)
{
let
offset
=
0
;
let
target
=
e
.
currentTarget
;
if
(
this
.
split
===
'vertical'
)
{
while
(
target
)
{
offset
+=
target
.
offsetLeft
;
target
=
target
.
offsetParent
;
}
const
currentPage
=
this
.
split
===
'vertical'
?
e
.
pageX
:
e
.
pageY
;
const
targetOffset
=
this
.
split
===
'vertical'
?
e
.
currentTarget
.
offsetWidth
:
e
.
currentTarget
.
offsetHeight
;
const
percent
=
Math
.
floor
(((
currentPage
-
offset
)
/
targetOffset
)
*
10000
)
/
100
;
if
(
percent
>
this
.
margin
&&
percent
<
100
-
this
.
margin
)
{
this
.
percent
=
percent
;
}
else
{
while
(
target
)
{
offset
+=
target
.
offsetTop
;
target
=
target
.
offsetParent
;
}
this
.
$emit
(
'resize'
);
this
.
hasMoved
=
true
;
}
const
currentPage
=
this
.
split
===
'vertical'
?
e
.
pageX
:
e
.
pageY
;
const
targetOffset
=
this
.
split
===
'vertical'
?
e
.
currentTarget
.
offsetWidth
:
e
.
currentTarget
.
offsetHeight
;
const
percent
=
Math
.
floor
(((
currentPage
-
offset
)
/
targetOffset
)
*
10000
)
/
100
;
if
(
percent
>
this
.
margin
&&
percent
<
100
-
this
.
margin
)
{
this
.
percent
=
percent
;
}
this
.
$emit
(
'resize'
);
this
.
hasMoved
=
true
;
}
}
}
}
</
script
>
<
style
scoped
>
.clearfix
:after
{
visibility
:
hidden
;
display
:
block
;
font-size
:
0
;
content
:
" "
;
clear
:
both
;
height
:
0
;
}
.vue-splitter-container
{
height
:
100%
;
/*display: flex;*/
position
:
relative
;
}
</
style
>
src/components/Sticky/index.vue
View file @
de992c50
<
template
>
<div
:style=
"
{height:height+'px',zIndex:zIndex}">
<div
:class=
"className"
:style=
"
{top:stickyTop+'px',zIndex:zIndex,position:position,width:width,height:height+'px'}">
<slot>
<div>
sticky
</div>
</slot>
</div>
<div
:style=
"
{height:height+'px',zIndex:zIndex}">
<div
:class=
"className"
:style=
"
{top:stickyTop+'px',zIndex:zIndex,position:position,width:width,height:height+'px'}">
<slot>
<div>
sticky
</div>
</slot>
</div>
</div>
</
template
>
<
script
>
export
default
{
name
:
'Sticky'
,
props
:
{
stickyTop
:
{
type
:
Number
,
default
:
0
},
zIndex
:
{
type
:
Number
,
default
:
1
},
className
:
{
type
:
String
}
export
default
{
name
:
'Sticky'
,
props
:
{
stickyTop
:
{
type
:
Number
,
default
:
0
},
data
()
{
return
{
active
:
false
,
position
:
''
,
currentTop
:
''
,
width
:
undefined
,
height
:
undefined
,
child
:
null
,
stickyHeight
:
0
};
zIndex
:
{
type
:
Number
,
default
:
1
},
methods
:
{
sticky
()
{
if
(
this
.
active
)
{
return
}
this
.
position
=
'fixed'
;
this
.
active
=
true
;
this
.
width
=
this
.
width
+
'px'
;
},
reset
()
{
if
(
!
this
.
active
)
{
return
}
this
.
position
=
''
;
this
.
width
=
'auto'
this
.
active
=
false
},
handleScroll
()
{
this
.
width
=
this
.
$el
.
getBoundingClientRect
().
width
;
const
offsetTop
=
this
.
$el
.
getBoundingClientRect
().
top
;
if
(
offsetTop
<=
this
.
stickyTop
)
{
this
.
sticky
();
return
}
this
.
reset
()
className
:
{
type
:
String
}
},
data
()
{
return
{
active
:
false
,
position
:
''
,
currentTop
:
''
,
width
:
undefined
,
height
:
undefined
,
child
:
null
,
stickyHeight
:
0
};
},
methods
:
{
sticky
()
{
if
(
this
.
active
)
{
return
}
this
.
position
=
'fixed'
;
this
.
active
=
true
;
this
.
width
=
this
.
width
+
'px'
;
},
mounted
()
{
this
.
height
=
this
.
$el
.
getBoundingClientRect
().
height
;
window
.
addEventListener
(
'scroll'
,
this
.
handleScroll
);
reset
()
{
if
(
!
this
.
active
)
{
return
}
this
.
position
=
''
;
this
.
width
=
'auto'
this
.
active
=
false
},
destroyed
()
{
window
.
removeEventListener
(
'scroll'
,
this
.
handleScroll
);
handleScroll
()
{
this
.
width
=
this
.
$el
.
getBoundingClientRect
().
width
;
const
offsetTop
=
this
.
$el
.
getBoundingClientRect
().
top
;
if
(
offsetTop
<=
this
.
stickyTop
)
{
this
.
sticky
();
return
}
this
.
reset
()
}
};
},
mounted
()
{
this
.
height
=
this
.
$el
.
getBoundingClientRect
().
height
;
window
.
addEventListener
(
'scroll'
,
this
.
handleScroll
);
},
destroyed
()
{
window
.
removeEventListener
(
'scroll'
,
this
.
handleScroll
);
}
};
</
script
>
src/components/Tinymce/index.vue
View file @
de992c50
...
...
@@ -6,79 +6,79 @@
<
script
>
// import { getToken, upload } from 'api/qiniu'; // 七牛
export
default
{
name
:
'tinymce'
,
props
:
{
id
:
{
type
:
String
,
default
:
'tinymceEditor'
},
value
:
{
type
:
String
,
default
:
''
},
toolbar
:
{
type
:
Array
,
required
:
false
,
default
()
{
return
[
'removeformat undo redo | bullist numlist | outdent indent | forecolor | fullscreen code'
,
'bold italic blockquote | h2 p media link | alignleft aligncenter alignright'
]
export
default
{
name
:
'tinymce'
,
props
:
{
id
:
{
type
:
String
,
default
:
'tinymceEditor'
},
value
:
{
type
:
String
,
default
:
''
},
toolbar
:
{
type
:
Array
,
required
:
false
,
default
()
{
return
[
'removeformat undo redo | bullist numlist | outdent indent | forecolor | fullscreen code'
,
'bold italic blockquote | h2 p media link | alignleft aligncenter alignright'
]
}
},
data
()
{
return
{
hasChange
:
false
,
hasInit
:
false
}
},
menubar
:
{
default
:
''
},
height
:
{
type
:
Number
,
required
:
false
,
default
:
360
}
},
data
()
{
return
{
hasChange
:
false
,
hasInit
:
false
watch
:
{
value
(
val
)
{
if
(
!
this
.
hasChange
&&
this
.
hasInit
)
{
this
.
$nextTick
(()
=>
tinymce
.
get
(
this
.
id
).
setContent
(
val
))
}
}
},
menubar
:
{
default
:
''
},
height
:
{
type
:
Number
,
required
:
false
,
default
:
360
}
},
watch
:
{
value
(
val
)
{
if
(
!
this
.
hasChange
&&
this
.
hasInit
)
{
this
.
$nextTick
(()
=>
tinymce
.
get
(
this
.
id
).
setContent
(
val
))
}
}
},
mounted
()
{
const
_this
=
this
;
tinymce
.
init
({
selector
:
`#
${
this
.
id
}
`
,
height
:
this
.
height
,
body_class
:
'panel-body '
,
object_resizing
:
false
,
mounted
()
{
const
_this
=
this
;
tinymce
.
init
({
selector
:
`#
${
this
.
id
}
`
,
height
:
this
.
height
,
body_class
:
'panel-body '
,
object_resizing
:
false
,
// language: 'zh_CN',
// language_url: '/static/tinymce/langs/zh_CN.js',
toolbar
:
this
.
toolbar
,
menubar
:
this
.
menubar
,
plugins
:
'advlist,autolink,code,paste,textcolor, colorpicker,fullscreen,link,lists,media,wordcount, imagetools,watermark'
,
end_container_on_empty_block
:
true
,
powerpaste_word_import
:
'clean'
,
code_dialog_height
:
450
,
code_dialog_width
:
1000
,
advlist_bullet_styles
:
'square'
,
advlist_number_styles
:
'default'
,
block_formats
:
'普通标签=p;小标题=h2;'
,
imagetools_cors_hosts
:
[
'wpimg.wallstcn.com'
,
'wallstreetcn.com'
],
imagetools_toolbar
:
'watermark'
,
default_link_target
:
'_blank'
,
link_title
:
false
,
init_instance_callback
:
editor
=>
{
if
(
_this
.
value
)
{
editor
.
setContent
(
_this
.
value
)
}
_this
.
hasInit
=
true
;
editor
.
on
(
'NodeChange Change KeyUp'
,
()
=>
{
this
.
hasChange
=
true
;
this
.
$emit
(
'input'
,
editor
.
getContent
({
format
:
'raw'
}));
});
},
toolbar
:
this
.
toolbar
,
menubar
:
this
.
menubar
,
plugins
:
'advlist,autolink,code,paste,textcolor, colorpicker,fullscreen,link,lists,media,wordcount, imagetools,watermark'
,
end_container_on_empty_block
:
true
,
powerpaste_word_import
:
'clean'
,
code_dialog_height
:
450
,
code_dialog_width
:
1000
,
advlist_bullet_styles
:
'square'
,
advlist_number_styles
:
'default'
,
block_formats
:
'普通标签=p;小标题=h2;'
,
imagetools_cors_hosts
:
[
'wpimg.wallstcn.com'
,
'wallstreetcn.com'
],
imagetools_toolbar
:
'watermark'
,
default_link_target
:
'_blank'
,
link_title
:
false
,
init_instance_callback
:
editor
=>
{
if
(
_this
.
value
)
{
editor
.
setContent
(
_this
.
value
)
}
_this
.
hasInit
=
true
;
editor
.
on
(
'NodeChange Change KeyUp'
,
()
=>
{
this
.
hasChange
=
true
;
this
.
$emit
(
'input'
,
editor
.
getContent
({
format
:
'raw'
}));
});
},
// 整合七牛上传
// images_dataimg_filter(img) {
// setTimeout(() => {
...
...
@@ -112,44 +112,44 @@
// console.log(err);
// });
// },
setup
(
editor
)
{
editor
.
addButton
(
'h2'
,
{
title
:
'小标题'
,
// tooltip text seen on mouseover
text
:
'小标题'
,
onclick
()
{
editor
.
execCommand
(
'mceToggleFormat'
,
false
,
'h2'
);
},
onPostRender
()
{
const
btn
=
this
;
editor
.
on
(
'init'
,
()
=>
{
editor
.
formatter
.
formatChanged
(
'h2'
,
state
=>
{
btn
.
active
(
state
);
setup
(
editor
)
{
editor
.
addButton
(
'h2'
,
{
title
:
'小标题'
,
// tooltip text seen on mouseover
text
:
'小标题'
,
onclick
()
{
editor
.
execCommand
(
'mceToggleFormat'
,
false
,
'h2'
);
},
onPostRender
()
{
const
btn
=
this
;
editor
.
on
(
'init'
,
()
=>
{
editor
.
formatter
.
formatChanged
(
'h2'
,
state
=>
{
btn
.
active
(
state
);
});
});
}
);
}
});
editor
.
addButton
(
'p'
,
{
title
:
'正文'
,
text
:
'正文'
,
onclick
()
{
editor
.
execCommand
(
'mceToggleFormat'
,
false
,
'p'
);
},
onPostRender
()
{
const
btn
=
this
;
editor
.
on
(
'init'
,
()
=>
{
editor
.
formatter
.
formatChanged
(
'p'
,
state
=>
{
btn
.
active
(
state
);
}
}
);
editor
.
addButton
(
'p'
,
{
title
:
'正文'
,
text
:
'正文'
,
onclick
()
{
editor
.
execCommand
(
'mceToggleFormat'
,
false
,
'p'
);
},
onPostRender
()
{
const
btn
=
this
;
editor
.
on
(
'init'
,
()
=>
{
editor
.
formatter
.
formatChanged
(
'p'
,
state
=>
{
btn
.
active
(
state
);
}
);
});
});
}
});
}
});
},
destroyed
()
{
tinymce
.
get
(
this
.
id
).
destroy
();
}
}
}
});
}
});
},
destroyed
()
{
tinymce
.
get
(
this
.
id
).
destroy
();
}
}
</
script
>
<
style
scoped
>
...
...
src/components/Upload/singleImage.vue
View file @
de992c50
<
template
>
<div
class=
"upload-container"
>
<el-upload
class=
"image-uploader"
:data=
"dataObj"
drag
:multiple=
"false"
:show-file-list=
"false"
action=
"https://httpbin.org/post"
:on-success=
"handleImageScucess"
>
<el-upload
class=
"image-uploader"
:data=
"dataObj"
drag
:multiple=
"false"
:show-file-list=
"false"
action=
"https://httpbin.org/post"
:on-success=
"handleImageScucess"
>
<i
class=
"el-icon-upload"
></i>
<div
class=
"el-upload__text"
>
将文件拖到此处,或
<em>
点击上传
</em></div>
</el-upload>
...
...
@@ -22,53 +15,54 @@
</div>
</div>
</
template
>
<
script
>
// 预览效果见付费文章
import
{
getToken
}
from
'api/qiniu'
;
export
default
{
name
:
'singleImageUpload'
,
props
:
{
value
:
String
},
computed
:
{
imageUrl
()
{
return
this
.
value
}
},
data
()
{
return
{
tempUrl
:
''
,
dataObj
:
{
token
:
''
,
key
:
''
}
};
},
methods
:
{
rmImage
()
{
this
.
emitInput
(
''
);
},
emitInput
(
val
)
{
this
.
$emit
(
'input'
,
val
);
},
handleImageScucess
()
{
this
.
emitInput
(
this
.
tempUrl
)
},
beforeUpload
()
{
const
_self
=
this
;
return
new
Promise
((
resolve
,
reject
)
=>
{
getToken
().
then
(
response
=>
{
const
key
=
response
.
data
.
qiniu_key
;
const
token
=
response
.
data
.
qiniu_token
;
_self
.
_data
.
dataObj
.
token
=
token
;
_self
.
_data
.
dataObj
.
key
=
key
;
this
.
tempUrl
=
response
.
data
.
qiniu_url
;
resolve
(
true
);
}).
catch
(
err
=>
{
console
.
log
(
err
);
reject
(
false
)
});
});
}
}
// 预览效果见付费文章
import
{
getToken
}
from
'api/qiniu'
;
export
default
{
name
:
'singleImageUpload'
,
props
:
{
value
:
String
},
computed
:
{
imageUrl
()
{
return
this
.
value
}
},
data
()
{
return
{
tempUrl
:
''
,
dataObj
:
{
token
:
''
,
key
:
''
}
};
},
methods
:
{
rmImage
()
{
this
.
emitInput
(
''
);
},
emitInput
(
val
)
{
this
.
$emit
(
'input'
,
val
);
},
handleImageScucess
()
{
this
.
emitInput
(
this
.
tempUrl
)
},
beforeUpload
()
{
const
_self
=
this
;
return
new
Promise
((
resolve
,
reject
)
=>
{
getToken
().
then
(
response
=>
{
const
key
=
response
.
data
.
qiniu_key
;
const
token
=
response
.
data
.
qiniu_token
;
_self
.
_data
.
dataObj
.
token
=
token
;
_self
.
_data
.
dataObj
.
key
=
key
;
this
.
tempUrl
=
response
.
data
.
qiniu_url
;
resolve
(
true
);
}).
catch
(
err
=>
{
console
.
log
(
err
);
reject
(
false
)
});
});
}
}
};
</
script
>
<
style
rel=
"stylesheet/scss"
lang=
"scss"
scoped
>
...
...
src/components/Upload/singleImage2.vue
View file @
de992c50
<
template
>
<div
class=
"singleImageUpload2 upload-container"
>
<el-upload
class=
"image-uploader"
:data=
"dataObj"
drag
:multiple=
"false"
:show-file-list=
"false"
action=
"https://httpbin.org/post"
:on-success=
"handleImageScucess"
>
<i
class=
"el-icon-upload"
></i>
<div
class=
"el-upload__text"
>
Drag或
<em>
点击上传
</em></div>
</el-upload>
<div
v-show=
"imageUrl.length>0"
class=
"image-preview"
>
<div
class=
"image-preview-wrapper"
v-show=
"imageUrl.length>1"
>
<img
:src=
"imageUrl"
>
<div
class=
"image-preview-action"
>
<i
@
click=
"rmImage"
class=
"el-icon-delete"
></i>
</div>
</div>
</div>
</div>
<div
class=
"singleImageUpload2 upload-container"
>
<el-upload
class=
"image-uploader"
:data=
"dataObj"
drag
:multiple=
"false"
:show-file-list=
"false"
action=
"https://httpbin.org/post"
:on-success=
"handleImageScucess"
>
<i
class=
"el-icon-upload"
></i>
<div
class=
"el-upload__text"
>
Drag或
<em>
点击上传
</em></div>
</el-upload>
<div
v-show=
"imageUrl.length>0"
class=
"image-preview"
>
<div
class=
"image-preview-wrapper"
v-show=
"imageUrl.length>1"
>
<img
:src=
"imageUrl"
>
<div
class=
"image-preview-action"
>
<i
@
click=
"rmImage"
class=
"el-icon-delete"
></i>
</div>
</div>
</div>
</div>
</
template
>
<
script
>
// 预览效果见专题
import
{
getToken
}
from
'api/qiniu'
;
export
default
{
name
:
'singleImageUpload2'
,
props
:
{
value
:
String
},
computed
:
{
imageUrl
()
{
return
this
.
value
}
},
data
()
{
return
{
tempUrl
:
''
,
dataObj
:
{
token
:
''
,
key
:
''
}
};
},
methods
:
{
rmImage
()
{
this
.
emitInput
(
''
);
},
emitInput
(
val
)
{
this
.
$emit
(
'input'
,
val
);
},
handleImageScucess
()
{
this
.
emitInput
(
this
.
tempUrl
)
},
beforeUpload
()
{
const
_self
=
this
;
return
new
Promise
((
resolve
,
reject
)
=>
{
getToken
().
then
(
response
=>
{
const
key
=
response
.
data
.
qiniu_key
;
const
token
=
response
.
data
.
qiniu_token
;
_self
.
_data
.
dataObj
.
token
=
token
;
_self
.
_data
.
dataObj
.
key
=
key
;
this
.
tempUrl
=
response
.
data
.
qiniu_url
;
resolve
(
true
);
}).
catch
(
err
=>
{
console
.
log
(
err
);
reject
(
false
)
});
});
}
}
// 预览效果见专题
import
{
getToken
}
from
'api/qiniu'
;
export
default
{
name
:
'singleImageUpload2'
,
props
:
{
value
:
String
},
computed
:
{
imageUrl
()
{
return
this
.
value
}
},
data
()
{
return
{
tempUrl
:
''
,
dataObj
:
{
token
:
''
,
key
:
''
}
};
},
methods
:
{
rmImage
()
{
this
.
emitInput
(
''
);
},
emitInput
(
val
)
{
this
.
$emit
(
'input'
,
val
);
},
handleImageScucess
()
{
this
.
emitInput
(
this
.
tempUrl
)
},
beforeUpload
()
{
const
_self
=
this
;
return
new
Promise
((
resolve
,
reject
)
=>
{
getToken
().
then
(
response
=>
{
const
key
=
response
.
data
.
qiniu_key
;
const
token
=
response
.
data
.
qiniu_token
;
_self
.
_data
.
dataObj
.
token
=
token
;
_self
.
_data
.
dataObj
.
key
=
key
;
this
.
tempUrl
=
response
.
data
.
qiniu_url
;
resolve
(
true
);
}).
catch
(
err
=>
{
console
.
log
(
err
);
reject
(
false
)
});
});
}
}
};
</
script
>
<
style
rel=
"stylesheet/scss"
lang=
"scss"
scoped
>
.upload-container
{
width
:
100%
;
height
:
100%
;
position
:
relative
;
.image-uploader
{
height
:
100%
;
}
.image-preview
{
width
:
100%
;
height
:
100%
;
position
:
absolute
;
left
:
0px
;
top
:
0px
;
border
:
1px
dashed
#d9d9d9
;
.image-preview-wrapper
{
position
:
relative
;
width
:
100%
;
height
:
100%
;
img
{
width
:
100%
;
height
:
100%
;
}
}
.image-preview-action
{
position
:
absolute
;
width
:
100%
;
height
:
100%
;
left
:
0
;
top
:
0
;
cursor
:
default
;
text-align
:
center
;
color
:
#fff
;
opacity
:
0
;
font-size
:
20px
;
background-color
:
rgba
(
0
,
0
,
0
,
.5
);
transition
:
opacity
.3s
;
cursor
:
pointer
;
text-align
:
center
;
line-height
:
200px
;
.el-icon-delete
{
font-size
:
36px
;
}
}
&
:hover
{
.image-preview-action
{
opacity
:
1
;
}
}
}
}
.upload-container
{
width
:
100%
;
height
:
100%
;
position
:
relative
;
.image-uploader
{
height
:
100%
;
}
.image-preview
{
width
:
100%
;
height
:
100%
;
position
:
absolute
;
left
:
0px
;
top
:
0px
;
border
:
1px
dashed
#d9d9d9
;
.image-preview-wrapper
{
position
:
relative
;
width
:
100%
;
height
:
100%
;
img
{
width
:
100%
;
height
:
100%
;
}
}
.image-preview-action
{
position
:
absolute
;
width
:
100%
;
height
:
100%
;
left
:
0
;
top
:
0
;
cursor
:
default
;
text-align
:
center
;
color
:
#fff
;
opacity
:
0
;
font-size
:
20px
;
background-color
:
rgba
(
0
,
0
,
0
,
.5
);
transition
:
opacity
.3s
;
cursor
:
pointer
;
text-align
:
center
;
line-height
:
200px
;
.el-icon-delete
{
font-size
:
36px
;
}
}
&
:hover
{
.image-preview-action
{
opacity
:
1
;
}
}
}
}
</
style
>
src/components/Upload/singleImage3.vue
View file @
de992c50
<
template
>
<div
class=
"upload-container"
>
<el-upload
class=
"image-uploader"
:data=
"dataObj"
drag
:multiple=
"false"
:show-file-list=
"false"
action=
"https://httpbin.org/post"
:on-success=
"handleImageScucess"
>
<i
class=
"el-icon-upload"
></i>
<div
class=
"el-upload__text"
>
将文件拖到此处,或
<em>
点击上传
</em></div>
</el-upload>
<div
class=
"image-preview image-app-preview"
>
<div
class=
"image-preview-wrapper"
v-show=
"imageUrl.length>1"
>
<div
class=
'app-fake-conver'
>
&
nbsp
&
nbsp全球 付费节目单 最热 经济
</div>
<img
:src=
"imageUrl"
>
<div
class=
"image-preview-action"
>
<i
@
click=
"rmImage"
class=
"el-icon-delete"
></i>
</div>
</div>
</div>
<div
class=
"image-preview"
>
<div
class=
"image-preview-wrapper"
v-show=
"imageUrl.length>1"
>
<img
:src=
"imageUrl"
>
<div
class=
"image-preview-action"
>
<i
@
click=
"rmImage"
class=
"el-icon-delete"
></i>
</div>
</div>
</div>
</div>
<div
class=
"upload-container"
>
<el-upload
class=
"image-uploader"
:data=
"dataObj"
drag
:multiple=
"false"
:show-file-list=
"false"
action=
"https://httpbin.org/post"
:on-success=
"handleImageScucess"
>
<i
class=
"el-icon-upload"
></i>
<div
class=
"el-upload__text"
>
将文件拖到此处,或
<em>
点击上传
</em></div>
</el-upload>
<div
class=
"image-preview image-app-preview"
>
<div
class=
"image-preview-wrapper"
v-show=
"imageUrl.length>1"
>
<div
class=
'app-fake-conver'
>
&
nbsp
&
nbsp全球 付费节目单 最热 经济
</div>
<img
:src=
"imageUrl"
>
<div
class=
"image-preview-action"
>
<i
@
click=
"rmImage"
class=
"el-icon-delete"
></i>
</div>
</div>
</div>
<div
class=
"image-preview"
>
<div
class=
"image-preview-wrapper"
v-show=
"imageUrl.length>1"
>
<img
:src=
"imageUrl"
>
<div
class=
"image-preview-action"
>
<i
@
click=
"rmImage"
class=
"el-icon-delete"
></i>
</div>
</div>
</div>
</div>
</
template
>
<
script
>
// 预览效果见文章
import
{
getToken
}
from
'api/qiniu'
;
export
default
{
name
:
'singleImageUpload'
,
props
:
{
value
:
String
},
computed
:
{
imageUrl
()
{
return
this
.
value
}
},
data
()
{
return
{
tempUrl
:
''
,
dataObj
:
{
token
:
''
,
key
:
''
}
};
},
methods
:
{
rmImage
()
{
this
.
emitInput
(
''
);
},
emitInput
(
val
)
{
this
.
$emit
(
'input'
,
val
);
},
handleImageScucess
(
file
)
{
this
.
emitInput
(
file
.
files
.
file
)
},
beforeUpload
()
{
const
_self
=
this
;
return
new
Promise
((
resolve
,
reject
)
=>
{
getToken
().
then
(
response
=>
{
const
key
=
response
.
data
.
qiniu_key
;
const
token
=
response
.
data
.
qiniu_token
;
_self
.
_data
.
dataObj
.
token
=
token
;
_self
.
_data
.
dataObj
.
key
=
key
;
this
.
tempUrl
=
response
.
data
.
qiniu_url
;
resolve
(
true
);
}).
catch
(
err
=>
{
console
.
log
(
err
);
reject
(
false
)
});
});
}
}
// 预览效果见文章
import
{
getToken
}
from
'api/qiniu'
;
export
default
{
name
:
'singleImageUpload'
,
props
:
{
value
:
String
},
computed
:
{
imageUrl
()
{
return
this
.
value
}
},
data
()
{
return
{
tempUrl
:
''
,
dataObj
:
{
token
:
''
,
key
:
''
}
};
},
methods
:
{
rmImage
()
{
this
.
emitInput
(
''
);
},
emitInput
(
val
)
{
this
.
$emit
(
'input'
,
val
);
},
handleImageScucess
(
file
)
{
this
.
emitInput
(
file
.
files
.
file
)
},
beforeUpload
()
{
const
_self
=
this
;
return
new
Promise
((
resolve
,
reject
)
=>
{
getToken
().
then
(
response
=>
{
const
key
=
response
.
data
.
qiniu_key
;
const
token
=
response
.
data
.
qiniu_token
;
_self
.
_data
.
dataObj
.
token
=
token
;
_self
.
_data
.
dataObj
.
key
=
key
;
this
.
tempUrl
=
response
.
data
.
qiniu_url
;
resolve
(
true
);
}).
catch
(
err
=>
{
console
.
log
(
err
);
reject
(
false
)
});
});
}
}
};
</
script
>
<
style
rel=
"stylesheet/scss"
lang=
"scss"
scoped
>
@import
"src/styles/mixin.scss"
;
.upload-container
{
width
:
100%
;
position
:
relative
;
@include
clearfix
;
.image-uploader
{
width
:
35%
;
float
:
left
;
}
.image-preview
{
width
:
200px
;
height
:
200px
;
position
:
relative
;
border
:
1px
dashed
#d9d9d9
;
float
:
left
;
margin-left
:
50px
;
.image-preview-wrapper
{
position
:
relative
;
width
:
100%
;
height
:
100%
;
img
{
width
:
100%
;
height
:
100%
;
}
}
.image-preview-action
{
position
:
absolute
;
width
:
100%
;
height
:
100%
;
left
:
0
;
top
:
0
;
cursor
:
default
;
text-align
:
center
;
color
:
#fff
;
opacity
:
0
;
font-size
:
20px
;
background-color
:
rgba
(
0
,
0
,
0
,
.5
);
transition
:
opacity
.3s
;
cursor
:
pointer
;
text-align
:
center
;
line-height
:
200px
;
.el-icon-delete
{
font-size
:
36px
;
}
}
&
:hover
{
.image-preview-action
{
opacity
:
1
;
}
}
}
.image-app-preview
{
width
:
320px
;
height
:
180px
;
position
:
relative
;
border
:
1px
dashed
#d9d9d9
;
float
:
left
;
margin-left
:
50px
;
.app-fake-conver
{
height
:
44px
;
position
:
absolute
;
width
:
100%
;
// background: rgba(0, 0, 0, .1);
text-align
:
center
;
line-height
:
64px
;
color
:
#fff
;
}
}
}
@import
"src/styles/mixin.scss"
;
.upload-container
{
width
:
100%
;
position
:
relative
;
@include
clearfix
;
.image-uploader
{
width
:
35%
;
float
:
left
;
}
.image-preview
{
width
:
200px
;
height
:
200px
;
position
:
relative
;
border
:
1px
dashed
#d9d9d9
;
float
:
left
;
margin-left
:
50px
;
.image-preview-wrapper
{
position
:
relative
;
width
:
100%
;
height
:
100%
;
img
{
width
:
100%
;
height
:
100%
;
}
}
.image-preview-action
{
position
:
absolute
;
width
:
100%
;
height
:
100%
;
left
:
0
;
top
:
0
;
cursor
:
default
;
text-align
:
center
;
color
:
#fff
;
opacity
:
0
;
font-size
:
20px
;
background-color
:
rgba
(
0
,
0
,
0
,
.5
);
transition
:
opacity
.3s
;
cursor
:
pointer
;
text-align
:
center
;
line-height
:
200px
;
.el-icon-delete
{
font-size
:
36px
;
}
}
&
:hover
{
.image-preview-action
{
opacity
:
1
;
}
}
}
.image-app-preview
{
width
:
320px
;
height
:
180px
;
position
:
relative
;
border
:
1px
dashed
#d9d9d9
;
float
:
left
;
margin-left
:
50px
;
.app-fake-conver
{
height
:
44px
;
position
:
absolute
;
width
:
100%
;
// background: rgba(0, 0, 0, .1);
text-align
:
center
;
line-height
:
64px
;
color
:
#fff
;
}
}
}
</
style
>
src/components/jsonEditor/index.vue
View file @
de992c50
...
...
@@ -4,61 +4,61 @@
</div>
</
template
>
<
script
>
import
CodeMirror
from
'codemirror'
;
import
'codemirror/addon/lint/lint.css'
;
import
'codemirror/lib/codemirror.css'
;
import
'codemirror/theme/rubyblue.css'
;
require
(
'script-loader!jsonlint'
);
import
'codemirror/mode/javascript/javascript'
import
'codemirror/addon/lint/lint'
import
'codemirror/addon/lint/json-lint'
;
import
CodeMirror
from
'codemirror'
;
import
'codemirror/addon/lint/lint.css'
;
import
'codemirror/lib/codemirror.css'
;
import
'codemirror/theme/rubyblue.css'
;
require
(
'script-loader!jsonlint'
);
import
'codemirror/mode/javascript/javascript'
import
'codemirror/addon/lint/lint'
import
'codemirror/addon/lint/json-lint'
;
export
default
{
name
:
'jsonEditor'
,
data
()
{
return
{
jsonEditor
:
false
}
},
props
:
[
'value'
],
watch
:
{
value
(
value
)
{
const
editor_value
=
this
.
jsonEditor
.
getValue
();
if
(
value
!==
editor_value
)
{
this
.
jsonEditor
.
setValue
(
JSON
.
stringify
(
this
.
value
,
null
,
2
));
}
export
default
{
name
:
'jsonEditor'
,
data
()
{
return
{
jsonEditor
:
false
}
},
props
:
[
'value'
],
watch
:
{
value
(
value
)
{
const
editor_value
=
this
.
jsonEditor
.
getValue
();
if
(
value
!==
editor_value
)
{
this
.
jsonEditor
.
setValue
(
JSON
.
stringify
(
this
.
value
,
null
,
2
));
}
},
mounted
()
{
this
.
jsonEditor
=
CodeMirror
.
fromTextArea
(
this
.
$refs
.
textarea
,
{
lineNumbers
:
true
,
mode
:
'application/json'
,
gutters
:
[
'CodeMirror-lint-markers'
],
theme
:
'rubyblue'
,
lint
:
true
});
}
},
mounted
()
{
this
.
jsonEditor
=
CodeMirror
.
fromTextArea
(
this
.
$refs
.
textarea
,
{
lineNumbers
:
true
,
mode
:
'application/json'
,
gutters
:
[
'CodeMirror-lint-markers'
],
theme
:
'rubyblue'
,
lint
:
true
});
this
.
jsonEditor
.
setValue
(
JSON
.
stringify
(
this
.
value
,
null
,
2
));
this
.
jsonEditor
.
on
(
'change'
,
cm
=>
{
this
.
$emit
(
'changed'
,
cm
.
getValue
())
this
.
$emit
(
'input'
,
cm
.
getValue
())
})
},
methods
:
{
getValue
()
{
return
this
.
jsonEditor
.
getValue
()
}
this
.
jsonEditor
.
setValue
(
JSON
.
stringify
(
this
.
value
,
null
,
2
));
this
.
jsonEditor
.
on
(
'change'
,
cm
=>
{
this
.
$emit
(
'changed'
,
cm
.
getValue
())
this
.
$emit
(
'input'
,
cm
.
getValue
())
})
},
methods
:
{
getValue
()
{
return
this
.
jsonEditor
.
getValue
()
}
}
}
</
script
>
<
style
>
.CodeMirror
{
height
:
100%
;
}
.json-editor
.cm-s-rubyblue
span
.cm-string
{
color
:
#F08047
;
}
.CodeMirror
{
height
:
100%
;
}
.json-editor
.cm-s-rubyblue
span
.cm-string
{
color
:
#F08047
;
}
</
style
>
src/components/twoDndList/index.vue
View file @
de992c50
...
...
@@ -3,7 +3,7 @@
<div
class=
"twoDndList-list"
:style=
"
{width:width1}">
<h3>
{{
list1Title
}}
</h3>
<draggable
:list=
"list1"
class=
"dragArea"
:options=
"
{group:'article'}">
<div
class=
"list-complete-item"
v-for=
"element in list1"
>
<div
class=
"list-complete-item"
v-for=
"element in list1"
:key=
'element'
>
<div
class=
"list-complete-item-handle"
>
[
{{
element
.
author
}}
]
{{
element
.
title
}}
</div>
<div
style=
"position:absolute;right:0px;"
>
<span
style=
"float: right ;margin-top: -20px;margin-right:5px;"
@
click=
"deleteEle(element)"
>
...
...
@@ -17,7 +17,7 @@
<div
class=
"twoDndList-list"
:style=
"
{width:width2}">
<h3>
{{
list2Title
}}
</h3>
<draggable
:list=
"filterList2"
class=
"dragArea"
:options=
"
{group:'article'}">
<div
class=
"list-complete-item"
v-for=
"element in filterList2"
>
<div
class=
"list-complete-item"
v-for=
"element in filterList2"
:key=
'element'
>
<div
class=
'list-complete-item-handle2'
@
click=
"pushEle(element)"
>
[
{{
element
.
author
}}
]
{{
element
.
title
}}
</div>
</div>
</draggable>
...
...
@@ -26,131 +26,133 @@
</
template
>
<
script
>
import
draggable
from
'vuedraggable'
export
default
{
name
:
'twoDndList'
,
components
:
{
draggable
},
computed
:
{
filterList2
()
{
return
this
.
list2
.
filter
(
v
=>
{
if
(
this
.
isNotInList1
(
v
))
{
return
v
}
return
false
;
})
import
draggable
from
'vuedraggable'
export
default
{
name
:
'twoDndList'
,
components
:
{
draggable
},
computed
:
{
filterList2
()
{
return
this
.
list2
.
filter
(
v
=>
{
if
(
this
.
isNotInList1
(
v
))
{
return
v
}
return
false
;
})
}
},
props
:
{
list1
:
{
type
:
Array
,
default
()
{
return
[]
}
},
props
:
{
list1
:
{
type
:
Array
,
default
()
{
return
[]
}
},
list2
:
{
type
:
Array
,
default
()
{
return
[]
}
},
list1Title
:
{
type
:
String
,
default
:
'list1'
},
list2Title
:
{
type
:
String
,
default
:
'list2'
},
width1
:
{
type
:
String
,
default
:
'48%'
},
width2
:
{
type
:
String
,
default
:
'48%'
list2
:
{
type
:
Array
,
default
()
{
return
[]
}
},
methods
:
{
isNotInList1
(
v
)
{
return
this
.
list1
.
every
(
k
=>
v
.
id
!==
k
.
id
)
},
isNotInList2
(
v
)
{
return
this
.
list2
.
every
(
k
=>
v
.
id
!==
k
.
id
)
},
deleteEle
(
ele
)
{
for
(
const
item
of
this
.
list1
)
{
if
(
item
.
id
===
ele
.
id
)
{
const
index
=
this
.
list1
.
indexOf
(
item
);
this
.
list1
.
splice
(
index
,
1
)
break
}
}
if
(
this
.
isNotInList2
(
ele
))
{
this
.
list2
.
unshift
(
ele
)
list1Title
:
{
type
:
String
,
default
:
'list1'
},
list2Title
:
{
type
:
String
,
default
:
'list2'
},
width1
:
{
type
:
String
,
default
:
'48%'
},
width2
:
{
type
:
String
,
default
:
'48%'
}
},
methods
:
{
isNotInList1
(
v
)
{
return
this
.
list1
.
every
(
k
=>
v
.
id
!==
k
.
id
)
},
isNotInList2
(
v
)
{
return
this
.
list2
.
every
(
k
=>
v
.
id
!==
k
.
id
)
},
deleteEle
(
ele
)
{
for
(
const
item
of
this
.
list1
)
{
if
(
item
.
id
===
ele
.
id
)
{
const
index
=
this
.
list1
.
indexOf
(
item
);
this
.
list1
.
splice
(
index
,
1
)
break
}
},
pushEle
(
ele
)
{
this
.
list1
.
push
(
ele
)
}
if
(
this
.
isNotInList2
(
ele
))
{
this
.
list2
.
unshift
(
ele
)
}
},
pushEle
(
ele
)
{
this
.
list1
.
push
(
ele
)
}
}
}
</
script
>
<
style
rel=
"stylesheet/scss"
lang=
"scss"
scoped
>
.twoDndList
{
background
:
#fff
;
padding-bottom
:
40px
;
&
:after
{
content
:
""
;
display
:
table
;
clear
:
both
;
}
.twoDndList-list
{
float
:
left
;
padding-bottom
:
30px
;
&
:first-of-type
{
margin-right
:
2%
;
}
.dragArea
{
margin-top
:
15px
;
min-height
:
50px
;
padding-bottom
:
30px
;
}
}
.twoDndList
{
background
:
#fff
;
padding-bottom
:
40px
;
&
:after
{
content
:
""
;
display
:
table
;
clear
:
both
;
}
.twoDndList-list
{
float
:
left
;
padding-bottom
:
30px
;
&
:first-of-type
{
margin-right
:
2%
;
}
.list-complete-item
{
cursor
:
pointer
;
position
:
relative
;
font-size
:
14px
;
padding
:
5px
12px
;
margin-top
:
4px
;
border
:
1px
solid
#bfcbd9
;
transition
:
all
1s
;
.dragArea
{
margin-top
:
15px
;
min-height
:
50px
;
padding-bottom
:
30px
;
}
}
}
.list-complete-item-handle
{
overflow
:
hidden
;
text-overflow
:
ellipsis
;
white-space
:
nowrap
;
margin-right
:
50px
;
}
.list-complete-item-handle2
{
overflow
:
hidden
;
text-overflow
:
ellipsis
;
white-space
:
nowrap
;
margin-right
:
20px
;
}
.list-complete-item
{
cursor
:
pointer
;
position
:
relative
;
font-size
:
14px
;
padding
:
5px
12px
;
margin-top
:
4px
;
border
:
1px
solid
#bfcbd9
;
transition
:
all
1s
;
}
.list-complete-item.sortable-chosen
{
background
:
#4AB7BD
;
}
.list-complete-item-handle
{
overflow
:
hidden
;
text-overflow
:
ellipsis
;
white-space
:
nowrap
;
margin-right
:
50px
;
}
.list-complete-item.sortable-ghost
{
background
:
#30B08F
;
}
.list-complete-item-handle2
{
overflow
:
hidden
;
text-overflow
:
ellipsis
;
white-space
:
nowrap
;
margin-right
:
20px
;
}
.list-complete-enter
,
.list-complete-leave-active
{
opacity
:
0
;
}
.list-complete-item.sortable-chosen
{
background
:
#4AB7BD
;
}
.list-complete-item.sortable-ghost
{
background
:
#30B08F
;
}
.list-complete-enter
,
.list-complete-leave-active
{
opacity
:
0
;
}
</
style
>
src/filters/index.js
View file @
de992c50
...
...
@@ -24,7 +24,6 @@ export function parseTime(time, cFormat) {
time
=
+
time
*
1000
}
const
format
=
cFormat
||
'{y}-{m}-{d} {h}:{i}:{s}'
;
let
date
;
if
(
typeof
time
==
'object'
)
{
...
...
@@ -75,8 +74,6 @@ export function formatTime(time, option) {
}
}
/* 数字 格式化*/
export
function
nFormatter
(
num
,
digits
)
{
const
si
=
[
...
...
@@ -95,14 +92,12 @@ export function nFormatter(num, digits) {
return
num
.
toString
();
}
export
function
html2Text
(
val
)
{
const
div
=
document
.
createElement
(
'div'
);
div
.
innerHTML
=
val
;
return
div
.
textContent
||
div
.
innerText
;
}
export
function
toThousandslsFilter
(
num
)
{
return
(
+
num
||
0
).
toString
().
replace
(
/^-
?\d
+/g
,
m
=>
m
.
replace
(
/
(?=(?!\b)(\d{3})
+$
)
/g
,
','
));
}
src/main.js
View file @
de992c50
...
...
@@ -20,7 +20,6 @@ import vueWaves from './directive/waves';// 水波纹指令
import
errLog
from
'store/errLog'
;
// error log组件
import
'./mock/index.js'
;
// 该项目所有请求使用mockjs模拟
// register globally
Vue
.
component
(
'multiselect'
,
Multiselect
);
Vue
.
component
(
'Sticky'
,
Sticky
);
...
...
@@ -28,8 +27,6 @@ Vue.component('icon-svg', IconSvg)
Vue
.
use
(
ElementUI
);
Vue
.
use
(
vueWaves
);
Vue
.
config
.
productionTip
=
false
;
// register global utility filters.
Object
.
keys
(
filters
).
forEach
(
key
=>
{
Vue
.
filter
(
key
,
filters
[
key
])
...
...
@@ -78,11 +75,12 @@ router.beforeEach((to, from, next) => {
}
});
router
.
afterEach
(()
=>
{
NProgress
.
done
();
// 结束Progress
});
Vue
.
config
.
productionTip
=
false
;
// 生产环境错误日志
if
(
process
.
env
===
'production'
)
{
Vue
.
config
.
errorHandler
=
function
(
err
,
vm
)
{
...
...
src/mock/login.js
View file @
de992c50
...
...
@@ -6,25 +6,21 @@ const userMap = {
token
:
'admin'
,
introduction
:
'我是超级管理员'
,
avatar
:
'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif'
,
name
:
'Super Admin'
,
uid
:
'001'
name
:
'Super Admin'
},
editor
:
{
role
:
[
'editor'
],
token
:
'editor'
,
introduction
:
'我是编辑'
,
avatar
:
'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif'
,
name
:
'Normal Editor'
,
uid
:
'002'
name
:
'Normal Editor'
},
developer
:
{
role
:
[
'develop'
],
token
:
'develop'
,
introduction
:
'我是开发'
,
avatar
:
'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif'
,
name
:
'工程师小王'
,
uid
:
'003'
name
:
'工程师小王'
}
}
...
...
src/router/index.js
View file @
de992c50
...
...
@@ -29,7 +29,6 @@ const SplitPane = _import('components/splitpane');
const
CountTo
=
_import
(
'components/countTo'
);
const
Mixin
=
_import
(
'components/mixin'
);
/* charts */
const
chartIndex
=
_import
(
'charts/index'
);
const
KeyboardChart
=
_import
(
'charts/keyboard'
);
...
...
@@ -63,7 +62,6 @@ const Tab = _import('example/tab/index');
/* permission */
const
Permission
=
_import
(
'permission/index'
);
Vue
.
use
(
Router
);
/**
...
...
src/store/getters.js
View file @
de992c50
...
...
@@ -4,10 +4,7 @@ const getters = {
token
:
state
=>
state
.
user
.
token
,
avatar
:
state
=>
state
.
user
.
avatar
,
name
:
state
=>
state
.
user
.
name
,
uid
:
state
=>
state
.
user
.
uid
,
email
:
state
=>
state
.
user
.
email
,
introduction
:
state
=>
state
.
user
.
introduction
,
auth_type
:
state
=>
state
.
user
.
auth_type
,
status
:
state
=>
state
.
user
.
status
,
roles
:
state
=>
state
.
user
.
roles
,
setting
:
state
=>
state
.
user
.
setting
,
...
...
src/store/modules/user.js
View file @
de992c50
...
...
@@ -5,10 +5,7 @@ const user = {
state
:
{
user
:
''
,
status
:
''
,
email
:
''
,
code
:
''
,
uid
:
undefined
,
auth_type
:
''
,
token
:
Cookies
.
get
(
'Admin-Token'
),
name
:
''
,
avatar
:
''
,
...
...
@@ -20,21 +17,12 @@ const user = {
},
mutations
:
{
SET_AUTH_TYPE
:
(
state
,
type
)
=>
{
state
.
auth_type
=
type
;
},
SET_CODE
:
(
state
,
code
)
=>
{
state
.
code
=
code
;
},
SET_TOKEN
:
(
state
,
token
)
=>
{
state
.
token
=
token
;
},
SET_UID
:
(
state
,
uid
)
=>
{
state
.
uid
=
uid
;
},
SET_EMAIL
:
(
state
,
email
)
=>
{
state
.
email
=
email
;
},
SET_INTRODUCTION
:
(
state
,
introduction
)
=>
{
state
.
introduction
=
introduction
;
},
...
...
@@ -70,7 +58,6 @@ const user = {
const
data
=
response
.
data
;
Cookies
.
set
(
'Admin-Token'
,
response
.
data
.
token
);
commit
(
'SET_TOKEN'
,
data
.
token
);
commit
(
'SET_EMAIL'
,
email
);
resolve
();
}).
catch
(
error
=>
{
reject
(
error
);
...
...
@@ -78,7 +65,6 @@ const user = {
});
},
// 获取用户信息
GetInfo
({
commit
,
state
})
{
return
new
Promise
((
resolve
,
reject
)
=>
{
...
...
@@ -87,7 +73,6 @@ const user = {
commit
(
'SET_ROLES'
,
data
.
role
);
commit
(
'SET_NAME'
,
data
.
name
);
commit
(
'SET_AVATAR'
,
data
.
avatar
);
commit
(
'SET_UID'
,
data
.
uid
);
commit
(
'SET_INTRODUCTION'
,
data
.
introduction
);
resolve
(
response
);
}).
catch
(
error
=>
{
...
...
@@ -100,7 +85,7 @@ const user = {
LoginByThirdparty
({
commit
,
state
},
code
)
{
return
new
Promise
((
resolve
,
reject
)
=>
{
commit
(
'SET_CODE'
,
code
);
loginByThirdparty
(
state
.
status
,
state
.
email
,
state
.
code
,
state
.
auth_type
).
then
(
response
=>
{
loginByThirdparty
(
state
.
status
,
state
.
email
,
state
.
code
).
then
(
response
=>
{
commit
(
'SET_TOKEN'
,
response
.
data
.
token
);
Cookies
.
set
(
'Admin-Token'
,
response
.
data
.
token
);
resolve
();
...
...
@@ -110,7 +95,6 @@ const user = {
});
},
// 登出
LogOut
({
commit
,
state
})
{
return
new
Promise
((
resolve
,
reject
)
=>
{
...
...
src/views/charts/keyboard.vue
View file @
de992c50
...
...
@@ -7,10 +7,11 @@
</
template
>
<
script
>
import
keyboardChart
from
'components/Charts/keyboard'
;
export
default
{
components
:
{
keyboardChart
}
};
import
keyboardChart
from
'components/Charts/keyboard'
;
export
default
{
components
:
{
keyboardChart
}
};
</
script
>
<
style
scoped
>
...
...
src/views/charts/keyboard2.vue
View file @
de992c50
...
...
@@ -7,10 +7,11 @@
</
template
>
<
script
>
import
keyboardChart2
from
'components/Charts/keyboard2'
;
export
default
{
components
:
{
keyboardChart2
}
};
import
keyboardChart2
from
'components/Charts/keyboard2'
;
export
default
{
components
:
{
keyboardChart2
}
};
</
script
>
<
style
scoped
>
...
...
src/views/charts/line.vue
View file @
de992c50
...
...
@@ -7,10 +7,11 @@
</
template
>
<
script
>
import
lineMarker
from
'components/Charts/lineMarker'
;
export
default
{
components
:
{
lineMarker
}
};
import
lineMarker
from
'components/Charts/lineMarker'
;
export
default
{
components
:
{
lineMarker
}
};
</
script
>
<
style
scoped
>
...
...
src/views/charts/mixchart.vue
View file @
de992c50
...
...
@@ -7,10 +7,11 @@
</
template
>
<
script
>
import
mixChart
from
'components/Charts/mixChart'
;
export
default
{
components
:
{
mixChart
}
};
import
mixChart
from
'components/Charts/mixChart'
;
export
default
{
components
:
{
mixChart
}
};
</
script
>
<
style
scoped
>
...
...
src/views/components/avatarUpload.vue
View file @
de992c50
...
...
@@ -4,45 +4,46 @@
由于我在使用时它只有vue@1版本,而且有些业务的需求耦合到七牛等等原因吧,自己改造了一下,如果大家要使用的话,优先还是使用官方component
</code>
<
PanThumb
:image=
'image'
>
</PanThumb>
<
pan-thumb
:image=
'image'
></pan-thumb
>
<el-button
type=
"primary"
icon=
"upload"
style=
"position: absolute;bottom: 15px;margin-left: 40px;"
@
click=
"imagecropperShow=true"
>
修改头像
</el-button>
<ImageCropper
:width=
"300"
:height=
"300"
url=
"https://httpbin.org/post"
@
close=
'close'
@
crop-upload-success=
"cropSuccess"
:key=
"imagecropperKey"
v-show=
"imagecropperShow"
/>
<image-cropper
:width=
"300"
:height=
"300"
url=
"https://httpbin.org/post"
@
close=
'close'
@
crop-upload-success=
"cropSuccess"
:key=
"imagecropperKey"
v-show=
"imagecropperShow"
></image-cropper>
</div>
</
template
>
<
script
>
import
ImageCropper
from
'components/ImageCropper'
;
import
PanThumb
from
'components/PanThumb'
;
export
default
{
components
:
{
ImageCropper
,
PanThumb
},
data
()
{
return
{
imagecropperShow
:
false
,
imagecropperKey
:
0
,
image
:
'https://wpimg.wallstcn.com/577965b9-bb9e-4e02-9f0c-095b41417191'
}
import
ImageCropper
from
'components/ImageCropper'
;
import
PanThumb
from
'components/PanThumb'
;
export
default
{
components
:
{
ImageCropper
,
PanThumb
},
data
()
{
return
{
imagecropperShow
:
false
,
imagecropperKey
:
0
,
image
:
'https://wpimg.wallstcn.com/577965b9-bb9e-4e02-9f0c-095b41417191'
}
},
methods
:
{
cropSuccess
(
resData
)
{
this
.
imagecropperShow
=
false
;
this
.
imagecropperKey
=
this
.
imagecropperKey
+
1
;
this
.
image
=
resData
.
files
.
avatar
;
},
methods
:
{
cropSuccess
(
resData
)
{
this
.
imagecropperShow
=
false
;
this
.
imagecropperKey
=
this
.
imagecropperKey
+
1
;
this
.
image
=
resData
.
files
.
avatar
;
},
close
()
{
this
.
imagecropperShow
=
false
;
}
close
()
{
this
.
imagecropperShow
=
false
;
}
};
}
};
</
script
>
<
style
scoped
>
.avatar
{
width
:
200px
;
height
:
200px
;
border-radius
:
50%
;
}
.avatar
{
width
:
200px
;
height
:
200px
;
border-radius
:
50%
;
}
</
style
>
src/views/components/countTo.vue
View file @
de992c50
...
...
@@ -3,7 +3,7 @@
<code>
<a
href=
'https://github.com/PanJiaChen/vue-countTo'
target=
'_blank'
>
countTo component
</a></code>
<count-to
ref=
'example'
class=
'example'
:start-val=
'_startVal'
:end-val=
'_endVal'
:duration=
'_duration'
:decimals=
'_decimals'
:separator=
'_separator'
:prefix=
'_prefix'
:suffix=
'_suffix'
:autoplay=
'false'
/
>
:separator=
'_separator'
:prefix=
'_prefix'
:suffix=
'_suffix'
:autoplay=
'false'
></count-to
>
<div
style=
'margin-left: 25%;margin-top: 40px;'
>
<label
class=
"label"
for=
"startValInput"
>
startVal:
<input
type=
"number"
v-model
.
number=
'setStartVal'
name=
'startValInput'
/></label>
<label
class=
"label"
for=
"endValInput"
>
endVal:
<input
type=
"number"
v-model
.
number=
'setEndVal'
name=
'endVaInput'
/></label>
...
...
@@ -22,72 +22,72 @@
</
template
>
<
script
>
import
countTo
from
'vue-count-to'
;
export
default
{
components
:
{
countTo
},
data
()
{
return
{
setStartVal
:
0
,
setEndVal
:
2017
,
setDuration
:
4000
,
setDecimals
:
0
,
setSeparator
:
','
,
setSuffix
:
' rmb'
,
setPrefix
:
'¥ '
}
},
computed
:
{
_startVal
()
{
if
(
this
.
setStartVal
)
{
return
this
.
setStartVal
}
else
{
return
0
}
},
_endVal
()
{
if
(
this
.
setEndVal
)
{
return
this
.
setEndVal
}
else
{
return
0
}
},
_duration
()
{
if
(
this
.
setDuration
)
{
return
this
.
setDuration
}
else
{
return
100
}
},
_decimals
()
{
if
(
this
.
setDecimals
)
{
if
(
this
.
setDecimals
<
0
||
this
.
setDecimals
>
20
)
{
alert
(
'digits argument must be between 0 and 20'
)
return
0
}
return
this
.
setDecimals
}
else
{
return
0
}
},
_separator
()
{
return
this
.
setSeparator
},
_suffix
()
{
return
this
.
setSuffix
},
_prefix
()
{
return
this
.
setPrefix
}
},
methods
:
{
start
()
{
this
.
$refs
.
example
.
start
();
},
pauseResume
()
{
this
.
$refs
.
example
.
pauseResume
();
}
}
};
import
countTo
from
'vue-count-to'
;
export
default
{
components
:
{
countTo
},
data
()
{
return
{
setStartVal
:
0
,
setEndVal
:
2017
,
setDuration
:
4000
,
setDecimals
:
0
,
setSeparator
:
','
,
setSuffix
:
' rmb'
,
setPrefix
:
'¥ '
}
},
computed
:
{
_startVal
()
{
if
(
this
.
setStartVal
)
{
return
this
.
setStartVal
}
else
{
return
0
}
},
_endVal
()
{
if
(
this
.
setEndVal
)
{
return
this
.
setEndVal
}
else
{
return
0
}
},
_duration
()
{
if
(
this
.
setDuration
)
{
return
this
.
setDuration
}
else
{
return
100
}
},
_decimals
()
{
if
(
this
.
setDecimals
)
{
if
(
this
.
setDecimals
<
0
||
this
.
setDecimals
>
20
)
{
alert
(
'digits argument must be between 0 and 20'
)
return
0
}
return
this
.
setDecimals
}
else
{
return
0
}
},
_separator
()
{
return
this
.
setSeparator
},
_suffix
()
{
return
this
.
setSuffix
},
_prefix
()
{
return
this
.
setPrefix
}
},
methods
:
{
start
()
{
this
.
$refs
.
example
.
start
();
},
pauseResume
()
{
this
.
$refs
.
example
.
pauseResume
();
}
}
};
</
script
>
<
style
scoped
>
...
...
src/views/components/dndlist.vue
View file @
de992c50
...
...
@@ -2,35 +2,37 @@
<div
class=
"components-container"
>
<code>
drag-list base on
<a
href=
"https://github.com/SortableJS/Vue.Draggable"
target=
"_blank"
>
Vue.Draggable
</a></code>
<div
class=
"editor-container"
>
<
DndList
:list1=
"list1"
:list2=
"list2"
list1Title=
"头条列表"
list2Title=
"文章池"
/
>
<
dnd-list
:list1=
"list1"
:list2=
"list2"
list1Title=
"头条列表"
list2Title=
"文章池"
></dnd-list
>
</div>
</div>
</
template
>
<
script
>
import
DndList
from
'components/twoDndList'
import
{
getList
}
from
'api/article'
;
export
default
{
components
:
{
DndList
},
data
()
{
return
{
list1
:
[],
list2
:
[]
}
}
,
created
()
{
this
.
fetchData
();
},
methods
:
{
fetchData
()
{
this
.
listLoading
=
true
;
getList
(
this
.
listQuery
).
then
(
response
=>
{
this
.
list1
=
response
.
data
.
splice
(
0
,
5
);
this
.
list2
=
response
.
data
;
console
.
log
(
this
.
list1
,
this
.
list2
)
}
)
}
import
DndList
from
'components/twoDndList'
import
{
getList
}
from
'api/article'
;
export
default
{
components
:
{
DndList
},
data
()
{
return
{
list1
:
[],
list2
:
[]
}
},
created
()
{
this
.
fetchData
();
},
methods
:
{
fetchData
()
{
this
.
listLoading
=
true
;
getList
(
this
.
listQuery
).
then
(
response
=>
{
this
.
list1
=
response
.
data
.
splice
(
0
,
5
)
;
this
.
list2
=
response
.
data
;
console
.
log
(
this
.
list1
,
this
.
list2
)
}
)
}
};
}
};
</
script
>
src/views/components/dropzone.vue
View file @
de992c50
...
...
@@ -4,27 +4,27 @@
由于我司业务有特殊需求,而且要传七牛 所以没用第三方 选择了自己封装
</code>
<div
class=
"editor-container"
>
<Dropzone
v-on:dropzone-removedFile=
"dropzoneR"
v-on:dropzone-success=
"dropzoneS"
id=
"myVueDropzone"
url=
"https://httpbin.org/post"
></Dropzone>
<dropzone
v-on:dropzone-removedFile=
"dropzoneR"
v-on:dropzone-success=
"dropzoneS"
id=
"myVueDropzone"
url=
"https://httpbin.org/post"
></dropzone>
</div>
</div>
</
template
>
<
script
>
import
Dropzone
from
'components/Dropzone'
;
import
Dropzone
from
'components/Dropzone'
;
export
default
{
components
:
{
Dropzone
},
methods
:
{
dropzoneS
(
file
)
{
console
.
log
(
file
)
this
.
$message
({
message
:
'上传成功'
,
type
:
'success'
});
},
dropzoneR
(
file
)
{
console
.
log
(
file
)
this
.
$message
({
message
:
'删除成功'
,
type
:
'success'
});
}
export
default
{
components
:
{
Dropzone
},
methods
:
{
dropzoneS
(
file
)
{
console
.
log
(
file
)
this
.
$message
({
message
:
'上传成功'
,
type
:
'success'
});
},
dropzoneR
(
file
)
{
console
.
log
(
file
)
this
.
$message
({
message
:
'删除成功'
,
type
:
'success'
});
}
};
}
};
</
script
>
src/views/components/jsoneditor.vue
View file @
de992c50
...
...
@@ -8,16 +8,17 @@
</
template
>
<
script
>
import
jsonEditor
from
'components/jsonEditor'
;
const
jsonData
=
'[{"items":[{"market_type":"forexdata","symbol":"XAUUSD"},{"market_type":"forexdata","symbol":"UKOIL"},{"market_type":"forexdata","symbol":"CORN"}],"name":""},{"items":[{"market_type":"forexdata","symbol":"XAUUSD"},{"market_type":"forexdata","symbol":"XAGUSD"},{"market_type":"forexdata","symbol":"AUTD"},{"market_type":"forexdata","symbol":"AGTD"}],"name":"贵金属"},{"items":[{"market_type":"forexdata","symbol":"CORN"},{"market_type":"forexdata","symbol":"WHEAT"},{"market_type":"forexdata","symbol":"SOYBEAN"},{"market_type":"forexdata","symbol":"SUGAR"}],"name":"农产品"},{"items":[{"market_type":"forexdata","symbol":"UKOIL"},{"market_type":"forexdata","symbol":"USOIL"},{"market_type":"forexdata","symbol":"NGAS"}],"name":"能源化工"}]'
;
export
default
{
components
:
{
jsonEditor
},
data
()
{
return
{
value
:
JSON
.
parse
(
jsonData
)
}
import
jsonEditor
from
'components/jsonEditor'
;
const
jsonData
=
'[{"items":[{"market_type":"forexdata","symbol":"XAUUSD"},{"market_type":"forexdata","symbol":"UKOIL"},{"market_type":"forexdata","symbol":"CORN"}],"name":""},{"items":[{"market_type":"forexdata","symbol":"XAUUSD"},{"market_type":"forexdata","symbol":"XAGUSD"},{"market_type":"forexdata","symbol":"AUTD"},{"market_type":"forexdata","symbol":"AGTD"}],"name":"贵金属"},{"items":[{"market_type":"forexdata","symbol":"CORN"},{"market_type":"forexdata","symbol":"WHEAT"},{"market_type":"forexdata","symbol":"SOYBEAN"},{"market_type":"forexdata","symbol":"SUGAR"}],"name":"农产品"},{"items":[{"market_type":"forexdata","symbol":"UKOIL"},{"market_type":"forexdata","symbol":"USOIL"},{"market_type":"forexdata","symbol":"NGAS"}],"name":"能源化工"}]'
;
export
default
{
components
:
{
jsonEditor
},
data
()
{
return
{
value
:
JSON
.
parse
(
jsonData
)
}
};
}
};
</
script
>
<
style
scoped
>
...
...
src/views/components/markdown.vue
View file @
de992c50
...
...
@@ -2,7 +2,7 @@
<div
class=
"components-container"
>
<code>
Markdown 我们这里选用了
<a
href=
"https://github.com/sparksuite/simplemde-markdown-editor"
target=
"_blank"
>
simplemde-markdown-editor
</a>
,简单的用vue封装了一下
<a
target=
'_blank'
href=
'https://segmentfault.com/a/1190000009762198#articleHeader14'
>
相关文章
</a></code>
<div
class=
"editor-container"
>
<
MdEditor
id=
'contentEditor'
ref=
"contentEditor"
v-model=
'content'
:height=
"300"
:zIndex=
'20'
></MdE
ditor>
<
md-editor
id=
'contentEditor'
ref=
"contentEditor"
v-model=
'content'
:height=
"300"
:zIndex=
'20'
></md-e
ditor>
</div>
<el-button
@
click=
'markdown2Html'
style=
"margin-top:80px;"
type=
"primary"
>
转为HTML
<i
class=
"el-icon-document el-icon--right"
></i></el-button>
<div
v-html=
"html"
></div>
...
...
@@ -10,24 +10,24 @@
</
template
>
<
script
>
import
MdEditor
from
'components/MdEditor'
;
export
default
{
components
:
{
MdEditor
},
data
()
{
return
{
content
:
'## Simplemde'
,
html
:
''
}
},
methods
:
{
markdown2Html
()
{
import
(
'showdown'
).
then
(
showdown
=>
{
const
converter
=
new
showdown
.
Converter
();
this
.
html
=
converter
.
makeHtml
(
this
.
content
)
})
}
import
MdEditor
from
'components/MdEditor'
;
export
default
{
components
:
{
MdEditor
},
data
()
{
return
{
content
:
'## Simplemde'
,
html
:
''
}
};
},
methods
:
{
markdown2Html
()
{
import
(
'showdown'
).
then
(
showdown
=>
{
const
converter
=
new
showdown
.
Converter
();
this
.
html
=
converter
.
makeHtml
(
this
.
content
)
})
}
}
};
</
script
>
src/views/components/mixin.vue
View file @
de992c50
<
template
>
<div
class=
"components-container"
>
<div
class=
'component-item'
>
<
MD
input
name=
"name"
v-model=
"title"
required
:maxlength=
"100"
>
<
md-
input
name=
"name"
v-model=
"title"
required
:maxlength=
"100"
>
标题
</
MD
input>
</
md-
input>
<code
class=
'code-part'
>
Material Design 的input
</code>
</div>
<div
class=
'component-item'
>
<
PanT
humb
image=
'https://wpimg.wallstcn.com/577965b9-bb9e-4e02-9f0c-095b41417191'
>
<
pan-t
humb
image=
'https://wpimg.wallstcn.com/577965b9-bb9e-4e02-9f0c-095b41417191'
>
上海花裤衩
</
PanT
humb>
</
pan-t
humb>
<code
class=
'code-part'
>
图片hover效果
</code>
</div>
...
...
@@ -18,21 +18,21 @@
<el-button
v-waves
type=
"primary"
>
水波纹效果
</el-button>
<code
class=
'code-part'
>
水波纹 v-directive
</code>
</div>
</div>
</
template
>
<
script
>
import
MDi
nput
from
'components/MDinput'
;
import
PanThumb
from
'components/PanThumb'
;
import
MdI
nput
from
'components/MDinput'
;
import
PanThumb
from
'components/PanThumb'
;
export
default
{
components
:
{
MDinput
,
PanThumb
},
data
()
{
return
{
title
:
''
}
export
default
{
components
:
{
MdInput
,
PanThumb
},
data
()
{
return
{
title
:
''
}
};
}
};
</
script
>
<
style
scoped
>
...
...
src/views/components/splitpane.vue
View file @
de992c50
<
template
>
<div
class=
"components-container"
>
<code>
splitPane 如果你用过
<a
href=
'http://codepen.io/'
target=
'_blank'
>
codepen
</a>
,
<a
href=
'https://jsfiddle.net/'
target=
'_blank'
>
jsfiddle
</a>
就不会陌生了
<div
class=
"components-container"
>
<code>
splitPane 如果你用过
<a
href=
'http://codepen.io/'
target=
'_blank'
>
codepen
</a>
,
<a
href=
'https://jsfiddle.net/'
target=
'_blank'
>
jsfiddle
</a>
就不会陌生了
暂还没有时间开源封装好,日后补上
</code>
<splitP
ane
v-on:resize=
"resize"
split=
"vertical"
>
<template
slot=
"paneL"
>
<div
class=
"left-container"
></div>
</
template
>
<
template
slot=
"paneR"
>
<split-pane
split=
"horizontal"
>
<template
slot=
"paneL"
>
<div
class=
"top-container"
></div>
</
template
>
<
template
slot=
"paneR"
>
<div
class=
"bottom-container"
>
</div>
</
template
>
</split-pane>
</template>
</splitP
ane>
</div>
<split-p
ane
v-on:resize=
"resize"
split=
"vertical"
>
<template
slot=
"paneL"
>
<div
class=
"left-container"
></div>
</
template
>
<
template
slot=
"paneR"
>
<split-pane
split=
"horizontal"
>
<template
slot=
"paneL"
>
<div
class=
"top-container"
></div>
</
template
>
<
template
slot=
"paneR"
>
<div
class=
"bottom-container"
>
</div>
</
template
>
</split-pane>
</template>
</split-p
ane>
</div>
</template>
<
script
>
import
splitPane
from
'components/SplitPane'
export
default
{
components
:
{
splitPane
},
methods
:
{
resize
()
{
console
.
log
(
'resize'
)
}
import
splitPane
from
'components/SplitPane'
export
default
{
components
:
{
splitPane
},
methods
:
{
resize
()
{
console
.
log
(
'resize'
)
}
};
}
};
</
script
>
<
style
scoped
>
.components-container
{
position
:
relative
;
height
:
100vh
;
}
.left-container
{
background-color
:
#F38181
;
height
:
100%
;
}
.components-container
{
position
:
relative
;
height
:
100vh
;
}
.righ
t-container
{
background-color
:
#FCE38A
;
height
:
200px
;
}
.lef
t-container
{
background-color
:
#F38181
;
height
:
100%
;
}
.top-container
{
background-color
:
#FCE38A
;
width
:
100%
;
height
:
100%
;
}
.right-container
{
background-color
:
#FCE38A
;
height
:
200px
;
}
.bottom-container
{
width
:
100%
;
background-color
:
#95E1D3
;
height
:
100%
;
}
.top-container
{
background-color
:
#FCE38A
;
width
:
100%
;
height
:
100%
;
}
.bottom-container
{
width
:
100%
;
background-color
:
#95E1D3
;
height
:
100%
;
}
</
style
>
src/views/components/sticky.vue
View file @
de992c50
<
template
>
<div>
<
S
ticky
className=
"sub-navbar"
>
<
s
ticky
className=
"sub-navbar"
>
<el-dropdown
trigger=
"click"
>
<el-button>
平台
<i
class=
"el-icon-caret-bottom el-icon--right"
></i>
...
...
@@ -32,7 +32,7 @@
<el-button
style=
"margin-left: 10px;"
type=
"success"
>
发布
</el-button>
</
S
ticky>
</
s
ticky>
<div
class=
"components-container"
>
<code>
Sticky header 当页面滚动到预设的位置会吸附在顶部
</code>
...
...
@@ -90,33 +90,34 @@
<div>
我是占位
</div>
</div>
</div>
</template>
<
script
>
import
Sticky
from
'components/Sticky'
;
import
Sticky
from
'components/Sticky'
;
export
default
{
components
:
{
Sticky
},
data
()
{
return
{
time
:
''
,
url
:
''
,
platforms
:
[
'a-platform'
],
platformsOptions
:
[
export
default
{
components
:
{
Sticky
},
data
()
{
return
{
time
:
''
,
url
:
''
,
platforms
:
[
'a-platform'
],
platformsOptions
:
[
{
key
:
'a-platform'
,
name
:
'平台A'
},
{
key
:
'b-platform'
,
name
:
'平台B'
},
{
key
:
'c-platform'
,
name
:
'平台C'
}
],
pickerOptions
:
{
disabledDate
(
time
)
{
return
time
.
getTime
()
>
Date
.
now
();
}
],
pickerOptions
:
{
disabledDate
(
time
)
{
return
time
.
getTime
()
>
Date
.
now
();
}
}
}
};
}
};
</
script
>
<
style
scoped
>
.time-container
{
display
:
inline-block
;
...
...
src/views/components/tinymce.vue
View file @
de992c50
...
...
@@ -9,16 +9,16 @@
</
template
>
<
script
>
import
Tinymce
from
'components/Tinymce'
;
import
Tinymce
from
'components/Tinymce'
;
export
default
{
components
:
{
Tinymce
},
data
()
{
return
{
content
:
'Tinymce'
}
export
default
{
components
:
{
Tinymce
},
data
()
{
return
{
content
:
'Tinymce'
}
};
}
};
</
script
>
<
style
scoped
>
...
...
src/views/dashboard/default/index.vue
View file @
de992c50
<
template
>
<div
class=
"dashboard-editor-container"
>
<div
class=
" clearfix"
>
<PanThumb
style=
"float: left"
:image=
"avatar"
>
你的权限:
<span
class=
"pan-info-roles"
v-for=
"item in roles"
>
{{
item
}}
</span>
</PanThumb>
<a
href=
"https://github.com/PanJiaChen/vue-element-admin"
target=
"_blank"
class=
"github-corner"
aria-label=
"View source on Github"
>
<svg
width=
"80"
height=
"80"
viewBox=
"0 0 250 250"
style=
"fill:#4AB7BD; color:#fff; position: absolute; top: 50px; border: 0; right: 0;"
aria-hidden=
"true"
>
<path
d=
"M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"
></path>
<path
d=
"M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2"
fill=
"currentColor"
style=
"transform-origin: 130px 106px;"
class=
"octo-arm"
></path>
<path
d=
"M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z"
fill=
"currentColor"
class=
"octo-body"
></path>
</svg>
</a>
<div
class=
"info-container"
>
<span
class=
"display_name"
>
{{
name
}}
</span>
<span
style=
'font-size:20px;padding-top:20px;display:inline-block;'
>
普通编辑dashboard
</span>
</div>
</div>
<div>
<img
class=
'emptyGif'
:src=
"emptyGif"
>
</div>
</div>
<div
class=
"dashboard-editor-container"
>
<div
class=
" clearfix"
>
<pan-thumb
style=
"float: left"
:image=
"avatar"
>
你的权限:
<span
class=
"pan-info-roles"
v-for=
"item in roles"
>
{{
item
}}
</span>
</pan-thumb>
<a
href=
"https://github.com/PanJiaChen/vue-element-admin"
target=
"_blank"
class=
"github-corner"
aria-label=
"View source on Github"
>
<svg
width=
"80"
height=
"80"
viewBox=
"0 0 250 250"
style=
"fill:#4AB7BD; color:#fff; position: absolute; top: 50px; border: 0; right: 0;"
aria-hidden=
"true"
>
<path
d=
"M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"
></path>
<path
d=
"M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2"
fill=
"currentColor"
style=
"transform-origin: 130px 106px;"
class=
"octo-arm"
></path>
<path
d=
"M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z"
fill=
"currentColor"
class=
"octo-body"
></path>
</svg>
</a>
<div
class=
"info-container"
>
<span
class=
"display_name"
>
{{
name
}}
</span>
<span
style=
'font-size:20px;padding-top:20px;display:inline-block;'
>
普通编辑dashboard
</span>
</div>
</div>
<div>
<img
class=
'emptyGif'
:src=
"emptyGif"
>
</div>
</div>
</
template
>
<
script
>
import
{
mapGetters
}
from
'vuex'
;
import
PanThumb
from
'components/PanThumb'
;
export
default
{
name
:
'dashboard-default'
,
components
:
{
PanThumb
},
data
()
{
return
{
emptyGif
:
'https://wpimg.wallstcn.com/0e03b7da-db9e-4819-ba10-9016ddfdaed3'
}
},
computed
:
{
...
mapGetters
([
'name'
,
'avatar'
,
'email'
,
'uid'
,
'introduction'
,
'roles'
])
import
{
mapGetters
}
from
'vuex'
;
import
PanThumb
from
'components/PanThumb'
;
export
default
{
name
:
'dashboard-default'
,
components
:
{
PanThumb
},
data
()
{
return
{
emptyGif
:
'https://wpimg.wallstcn.com/0e03b7da-db9e-4819-ba10-9016ddfdaed3'
}
},
computed
:
{
...
mapGetters
([
'name'
,
'avatar'
,
'roles'
])
}
}
</
script
>
<
style
rel=
"stylesheet/scss"
lang=
"scss"
scoped
>
.emptyGif
{
display
:
block
;
width
:
45%
;
margin
:
0
auto
;
}
.dashboard-editor-container
{
background-color
:
#e3e3e3
;
min-height
:
100vh
;
margin-top
:
-50px
;
padding
:
100px
60px
0px
;
.pan-info-roles
{
font-size
:
12px
;
font-weight
:
700
;
color
:
#333
;
display
:
block
;
}
.info-container
{
position
:
relative
;
margin-left
:
190px
;
height
:
150px
;
line-height
:
200px
;
.display_name
{
font-size
:
48px
;
line-height
:
48px
;
color
:
#212121
;
position
:
absolute
;
top
:
25px
;
}
}
}
.emptyGif
{
display
:
block
;
width
:
45%
;
margin
:
0
auto
;
}
.dashboard-editor-container
{
background-color
:
#e3e3e3
;
min-height
:
100vh
;
margin-top
:
-50px
;
padding
:
100px
60px
0px
;
.pan-info-roles
{
font-size
:
12px
;
font-weight
:
700
;
color
:
#333
;
display
:
block
;
}
.info-container
{
position
:
relative
;
margin-left
:
190px
;
height
:
150px
;
line-height
:
200px
;
.display_name
{
font-size
:
48px
;
line-height
:
48px
;
color
:
#212121
;
position
:
absolute
;
top
:
25px
;
}
}
}
</
style
>
src/views/dashboard/editor/barChart.vue
View file @
de992c50
<
template
>
<div
:class=
"className"
:style=
"
{height:height,width:width}">
</div>
<div
:class=
"className"
:style=
"
{height:height,width:width}">
</div>
</
template
>
<
script
>
import
echarts
from
'echarts'
;
require
(
'echarts/theme/macarons'
);
// echarts 主题
...
...
src/views/dashboard/editor/index.vue
View file @
de992c50
<
template
>
<div
class=
"dashboard-editor-container"
>
<a
href=
"https://github.com/PanJiaChen/vue-element-admin"
target=
"_blank"
class=
"github-corner"
aria-label=
"View source on Github"
>
<svg
width=
"80"
height=
"80"
viewBox=
"0 0 250 250"
style=
"fill:#4AB7BD; color:#fff; position: absolute; top: 50px; border: 0; right: 0;"
aria-hidden=
"true"
>
<path
d=
"M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"
></path>
<path
d=
"M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2"
fill=
"currentColor"
style=
"transform-origin: 130px 106px;"
class=
"octo-arm"
></path>
<path
d=
"M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z"
fill=
"currentColor"
class=
"octo-body"
></path>
</svg>
</a>
<el-row
class=
"btn-group"
>
<el-col
:span=
"4"
class=
'text-center'
>
<router-link
class=
"pan-btn blue-btn"
to=
"/components/index"
>
Components
</router-link>
</el-col>
<el-col
:span=
"4"
class=
'text-center'
>
<router-link
class=
"pan-btn light-blue-btn"
to=
"/charts/index"
>
Charts
</router-link>
</el-col>
<el-col
:span=
"4"
class=
'text-center'
>
<router-link
class=
"pan-btn pink-btn"
to=
"/excel/download"
>
Excel
</router-link>
</el-col>
<el-col
:span=
"4"
class=
'text-center'
>
<router-link
class=
"pan-btn green-btn"
to=
"/example/table/table"
>
Table
</router-link>
</el-col>
<el-col
:span=
"4"
class=
'text-center'
>
<router-link
class=
"pan-btn tiffany-btn"
to=
"/example/form/edit"
>
Form
</router-link>
</el-col>
<el-col
:span=
"4"
class=
'text-center'
>
<router-link
class=
"pan-btn yellow-btn"
to=
"/example/form/edit"
>
Theme
</router-link>
</el-col>
</el-row>
<div
class=
"dashboard-editor-container"
>
<a
href=
"https://github.com/PanJiaChen/vue-element-admin"
target=
"_blank"
class=
"github-corner"
aria-label=
"View source on Github"
>
<svg
width=
"80"
height=
"80"
viewBox=
"0 0 250 250"
style=
"fill:#4AB7BD; color:#fff; position: absolute; top: 50px; border: 0; right: 0;"
aria-hidden=
"true"
>
<path
d=
"M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"
></path>
<path
d=
"M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2"
fill=
"currentColor"
style=
"transform-origin: 130px 106px;"
class=
"octo-arm"
></path>
<path
d=
"M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z"
fill=
"currentColor"
class=
"octo-body"
></path>
</svg>
</a>
<el-row
class=
"btn-group"
>
<el-col
:span=
"4"
class=
'text-center'
>
<router-link
class=
"pan-btn blue-btn"
to=
"/components/index"
>
Components
</router-link>
</el-col>
<el-col
:span=
"4"
class=
'text-center'
>
<router-link
class=
"pan-btn light-blue-btn"
to=
"/charts/index"
>
Charts
</router-link>
</el-col>
<el-col
:span=
"4"
class=
'text-center'
>
<router-link
class=
"pan-btn pink-btn"
to=
"/excel/download"
>
Excel
</router-link>
</el-col>
<el-col
:span=
"4"
class=
'text-center'
>
<router-link
class=
"pan-btn green-btn"
to=
"/example/table/table"
>
Table
</router-link>
</el-col>
<el-col
:span=
"4"
class=
'text-center'
>
<router-link
class=
"pan-btn tiffany-btn"
to=
"/example/form/edit"
>
Form
</router-link>
</el-col>
<el-col
:span=
"4"
class=
'text-center'
>
<router-link
class=
"pan-btn yellow-btn"
to=
"/example/form/edit"
>
Theme
</router-link>
</el-col>
</el-row>
<el-row>
<el-col
:span=
"6"
>
<el-card
class=
"box-card"
>
<div
slot=
"header"
class=
"box-card-header"
>
<pan-thumb
class=
"panThumb"
:image=
"avatar"
>
你的权限:
<span
class=
"pan-info-roles"
:key=
'item'
v-for=
"item in roles"
>
{{
item
}}
</span>
</pan-thumb>
</div>
<span
class=
"display_name"
>
{{
name
}}
</span>
<div
class=
"info-item"
>
<countTo
class=
"info-item-num"
:startVal=
'0'
:endVal=
'statisticsData.article_count'
:duration=
'3400'
></countTo>
<span
class=
"info-item-text"
>
文章
</span>
<icon-svg
icon-class=
"a"
class=
"dashboard-editor-icon"
></icon-svg>
</div>
<div
class=
"info-item"
>
<countTo
class=
"info-item-num"
:startVal=
'0'
:endVal=
'statisticsData.pageviews_count'
:duration=
'3600'
></countTo>
<span
class=
"info-item-text"
>
浏览量
</span>
<icon-svg
icon-class=
"b"
class=
"dashboard-editor-icon"
></icon-svg>
</div>
</el-card>
</el-col>
<el-row>
<el-col
:span=
"6"
>
<el-card
class=
"box-card"
>
<div
slot=
"header"
class=
"box-card-header"
>
<pan-thumb
class=
"panThumb"
:image=
"avatar"
>
你的权限:
<span
class=
"pan-info-roles"
:key=
'item'
v-for=
"item in roles"
>
{{
item
}}
</span>
</pan-thumb>
</div>
<span
class=
"display_name"
>
{{
name
}}
</span>
<div
class=
"info-item"
>
<countTo
class=
"info-item-num"
:startVal=
'0'
:endVal=
'statisticsData.article_count'
:duration=
'3400'
></countTo>
<span
class=
"info-item-text"
>
文章
</span>
<icon-svg
icon-class=
"a"
class=
"dashboard-editor-icon"
></icon-svg>
</div>
<div
class=
"info-item"
>
<countTo
class=
"info-item-num"
:startVal=
'0'
:endVal=
'statisticsData.pageviews_count'
:duration=
'3600'
></countTo>
<span
class=
"info-item-text"
>
浏览量
</span>
<icon-svg
icon-class=
"b"
class=
"dashboard-editor-icon"
></icon-svg>
</div>
</el-card>
</el-col>
<el-col
:span=
"8"
>
<pie-chart></pie-chart>
</el-col>
<el-col
:span=
"8"
>
<pie-chart></pie-chart>
</el-col>
<el-col
:span=
"10"
>
<bar-chart></bar-chart>
</el-col>
</el-row>
<el-col
:span=
"10"
>
<bar-chart></bar-chart>
</el-col>
</el-row>
<el-row
:gutter=
"20"
>
<el-col
:span=
"15"
>
<line-chart></line-chart>
</el-col>
<el-col
:span=
"9"
>
<todo-list></todo-list>
</el-col>
</el-row>
<el-row
:gutter=
"20"
>
<el-col
:span=
"15"
>
<line-chart></line-chart>
</el-col>
<el-col
:span=
"9"
>
<todo-list></todo-list>
</el-col>
</el-row>
</div>
</div>
</
template
>
<
script
>
import
{
mapGetters
}
from
'vuex'
;
import
panThumb
from
'components/PanThumb'
;
import
pieChart
from
'./pieChart'
;
import
barChart
from
'./barChart'
;
import
lineChart
from
'./lineChart'
;
import
countTo
from
'vue-count-to'
;
import
todoList
from
'components/TodoList'
;
export
default
{
name
:
'dashboard-editor'
,
components
:
{
panThumb
,
countTo
,
pieChart
,
lineChart
,
barChart
,
todoList
},
data
()
{
return
{
statisticsData
:
{
article_count
:
1024
,
comment_count
:
102400
,
latest_article
:
[],
month_article_count
:
28
,
pageviews_count
:
1024
}
}
},
computed
:
{
...
mapGetters
([
'name'
,
'avatar'
,
'roles'
])
import
{
mapGetters
}
from
'vuex'
;
import
panThumb
from
'components/PanThumb'
;
import
pieChart
from
'./pieChart'
;
import
barChart
from
'./barChart'
;
import
lineChart
from
'./lineChart'
;
import
countTo
from
'vue-count-to'
;
import
todoList
from
'components/TodoList'
;
export
default
{
name
:
'dashboard-editor'
,
components
:
{
panThumb
,
countTo
,
pieChart
,
lineChart
,
barChart
,
todoList
},
data
()
{
return
{
statisticsData
:
{
article_count
:
1024
,
comment_count
:
102400
,
latest_article
:
[],
month_article_count
:
28
,
pageviews_count
:
1024
}
}
},
computed
:
{
...
mapGetters
([
'name'
,
'avatar'
,
'roles'
])
}
}
</
script
>
<
style
rel=
"stylesheet/scss"
lang=
"scss"
scoped
>
...
...
src/views/dashboard/editor/lineChart.vue
View file @
de992c50
<
template
>
<div
:class=
"className"
:style=
"
{height:height,width:width}">
</div>
<div
:class=
"className"
:style=
"
{height:height,width:width}">
</div>
</
template
>
<
script
>
import
echarts
from
'echarts'
;
require
(
'echarts/theme/macarons'
);
// echarts 主题
import
{
debounce
}
from
'utils'
;
export
default
{
props
:
{
className
:
{
...
...
src/views/dashboard/editor/pieChart.vue
View file @
de992c50
<
template
>
<div
:class=
"className"
:style=
"
{height:height,width:width}">
</div>
<div
:class=
"className"
:style=
"
{height:height,width:width}">
</div>
</
template
>
<
script
>
import
echarts
from
'echarts'
;
require
(
'echarts/theme/macarons'
);
// echarts 主题
...
...
src/views/dashboard/index.vue
View file @
de992c50
<
template
>
<div
class=
"dashboard-container"
>
<component
v-bind:is=
"currentRole"
>
</component>
</div>
<div
class=
"dashboard-container"
>
<component
v-bind:is=
"currentRole"
>
</component>
</div>
</
template
>
<
script
>
import
{
mapGetters
}
from
'vuex'
;
import
EditorDashboard
from
'./editor/index'
;
import
DefaultDashboard
from
'./default/index'
;
export
default
{
name
:
'dashboard'
,
components
:
{
EditorDashboard
,
DefaultDashboard
},
data
()
{
return
{
currentRole
:
'EditorDashboard'
}
},
computed
:
{
...
mapGetters
([
'name'
,
'avatar'
,
'email'
,
'introduction'
,
'roles'
])
},
created
()
{
if
(
this
.
roles
.
indexOf
(
'admin'
)
>=
0
)
{
return
;
}
// const isEditor = this.roles.some(v => v.indexOf('editor') >= 0)
// if (!isEditor) {
// this.currentRole = 'DefaultDashboard';
// }
this
.
currentRole
=
'DefaultDashboard'
;
import
{
mapGetters
}
from
'vuex'
;
import
EditorDashboard
from
'./editor/index'
;
import
DefaultDashboard
from
'./default/index'
;
export
default
{
name
:
'dashboard'
,
components
:
{
EditorDashboard
,
DefaultDashboard
},
data
()
{
return
{
currentRole
:
'EditorDashboard'
}
},
computed
:
{
...
mapGetters
([
'name'
,
'avatar'
,
'email'
,
'introduction'
,
'roles'
])
},
created
()
{
if
(
this
.
roles
.
indexOf
(
'admin'
)
>=
0
)
{
return
;
}
this
.
currentRole
=
'DefaultDashboard'
;
}
}
</
script
>
src/views/errlog/index.vue
View file @
de992c50
<
template
>
<div
class=
"errPage-container"
>
<err-code
/
>
<err-code
></err-code
>
<h3>
请点击右上角bug小图表
</h3>
<code>
...
...
@@ -11,19 +11,15 @@
</
template
>
<
script
>
import
errCode
from
'./errcode'
;
export
default
{
components
:
{
errCode
},
methods
:
{
back
()
{
this
.
$router
.
go
(
-
1
)
}
}
};
import
errCode
from
'./errcode'
;
export
default
{
components
:
{
errCode
}
};
</
script
>
<
style
scoped
>
.errPage-container
{
padding
:
30px
;
}
.errPage-container
{
padding
:
30px
;
}
</
style
>
src/views/error/401.vue
View file @
de992c50
...
...
@@ -28,25 +28,25 @@
</
template
>
<
script
>
import
errGif
from
'assets/401.gif'
;
export
default
{
data
()
{
return
{
errGif
:
errGif
+
'?'
+
+
new
Date
(),
ewizardClap
:
'https://wpimg.wallstcn.com/007ef517-bafd-4066-aae4-6883632d9646'
,
dialogVisible
:
false
}
},
methods
:
{
back
()
{
if
(
this
.
$route
.
query
.
noGoBack
)
{
this
.
$router
.
push
({
path
:
'/dashboard'
});
}
else
{
this
.
$router
.
go
(
-
1
);
}
import
errGif
from
'assets/401_images/401.gif'
;
export
default
{
data
()
{
return
{
errGif
:
errGif
+
'?'
+
+
new
Date
(),
ewizardClap
:
'https://wpimg.wallstcn.com/007ef517-bafd-4066-aae4-6883632d9646'
,
dialogVisible
:
false
}
},
methods
:
{
back
()
{
if
(
this
.
$route
.
query
.
noGoBack
)
{
this
.
$router
.
push
({
path
:
'/dashboard'
});
}
else
{
this
.
$router
.
go
(
-
1
);
}
}
};
}
};
</
script
>
<
style
rel=
"stylesheet/scss"
lang=
"scss"
scoped
>
...
...
src/views/error/404.vue
View file @
de992c50
...
...
@@ -2,10 +2,10 @@
<div
style=
"background:#f0f2f5;margin-top: -20px;"
>
<div
class=
"wscn-http404"
>
<div
class=
"pic-404"
>
<img
class=
"pic-404__parent"
src=
"../../assets/404.png
"
alt=
"404"
>
<img
class=
"pic-404__child left"
src=
"../../assets/404_cloud.png
"
alt=
"404"
>
<img
class=
"pic-404__child mid"
src=
"../../assets/404_cloud.png
"
alt=
"404"
>
<img
class=
"pic-404__child right"
src=
"../../assets/404_cloud.png
"
alt=
"404"
>
<img
class=
"pic-404__parent"
:src=
"img_404
"
alt=
"404"
>
<img
class=
"pic-404__child left"
:src=
"img_404_cloud
"
alt=
"404"
>
<img
class=
"pic-404__child mid"
:src=
"img_404_cloud
"
alt=
"404"
>
<img
class=
"pic-404__child right"
:src=
"img_404_cloud
"
alt=
"404"
>
</div>
<div
class=
"bullshit"
>
<div
class=
"bullshit__oops"
>
OOPS!
</div>
...
...
@@ -19,7 +19,16 @@
</
template
>
<
script
>
import
img_404
from
'@/assets/404_images/404.png'
import
img_404_cloud
from
'@/assets/404_images/404_cloud.png'
export
default
{
data
()
{
return
{
img_404
,
img_404_cloud
}
},
computed
:
{
message
()
{
return
'特朗普说这个页面你不能进......'
...
...
@@ -29,191 +38,192 @@
</
script
>
<
style
rel=
"stylesheet/scss"
lang=
"scss"
scoped
>
.wscn-http404
{
.wscn-http404
{
position
:
relative
;
width
:
1200px
;
margin
:
20px
auto
60px
;
padding
:
0
100px
;
overflow
:
hidden
;
.pic-404
{
position
:
relative
;
width
:
1200px
;
margin
:
20px
auto
6
0px
;
padding
:
0
100px
;
float
:
left
;
width
:
60
0px
;
padding
:
150px
0
;
overflow
:
hidden
;
.pic-404
{
position
:
relative
;
float
:
left
;
width
:
600px
;
padding
:
150px
0
;
overflow
:
hidden
;
&
__parent
{
width
:
100%
;
&
__parent
{
width
:
100%
;
}
&
__child
{
position
:
absolute
;
&
.left
{
width
:
80px
;
top
:
17px
;
left
:
220px
;
opacity
:
0
;
animation-name
:
cloudLeft
;
animation-duration
:
2s
;
animation-timing-function
:
linear
;
animation-fill-mode
:
forwards
;
animation-delay
:
1s
;
}
&
__child
{
position
:
absolute
;
&
.left
{
width
:
80px
;
&
.mid
{
width
:
46px
;
top
:
10px
;
left
:
420px
;
opacity
:
0
;
animation-name
:
cloudMid
;
animation-duration
:
2s
;
animation-timing-function
:
linear
;
animation-fill-mode
:
forwards
;
animation-delay
:
1
.2s
;
}
&
.right
{
width
:
62px
;
top
:
100px
;
left
:
500px
;
opacity
:
0
;
animation-name
:
cloudRight
;
animation-duration
:
2s
;
animation-timing-function
:
linear
;
animation-fill-mode
:
forwards
;
animation-delay
:
1s
;
}
@keyframes
cloudLeft
{
0
%
{
top
:
17px
;
left
:
220px
;
opacity
:
0
;
animation-name
:
cloudLeft
;
animation-duration
:
2s
;
animation-timing-function
:
linear
;
animation-fill-mode
:
forwards
;
animation-delay
:
1s
;
}
&
.mid
{
width
:
46px
;
20
%
{
top
:
33px
;
left
:
188px
;
opacity
:
1
;
}
80
%
{
top
:
81px
;
left
:
92px
;
opacity
:
1
;
}
100
%
{
top
:
97px
;
left
:
60px
;
opacity
:
0
;
}
}
@keyframes
cloudMid
{
0
%
{
top
:
10px
;
left
:
420px
;
opacity
:
0
;
animation-name
:
cloudMid
;
animation-duration
:
2s
;
animation-timing-function
:
linear
;
animation-fill-mode
:
forwards
;
animation-delay
:
1
.2s
;
}
&
.right
{
width
:
62px
;
20
%
{
top
:
40px
;
left
:
360px
;
opacity
:
1
;
}
70
%
{
top
:
130px
;
left
:
180px
;
opacity
:
1
;
}
100
%
{
top
:
160px
;
left
:
120px
;
opacity
:
0
;
}
}
@keyframes
cloudRight
{
0
%
{
top
:
100px
;
left
:
500px
;
opacity
:
0
;
animation-name
:
cloudRight
;
animation-duration
:
2s
;
animation-timing-function
:
linear
;
animation-fill-mode
:
forwards
;
animation-delay
:
1s
;
}
@keyframes
cloudLeft
{
0
%
{
top
:
17px
;
left
:
220px
;
opacity
:
0
;
}
20
%
{
top
:
33px
;
left
:
188px
;
opacity
:
1
;
}
80
%
{
top
:
81px
;
left
:
92px
;
opacity
:
1
;
}
100
%
{
top
:
97px
;
left
:
60px
;
opacity
:
0
;
}
20
%
{
top
:
120px
;
left
:
460px
;
opacity
:
1
;
}
@keyframes
cloudMid
{
0
%
{
top
:
10px
;
left
:
420px
;
opacity
:
0
;
}
20
%
{
top
:
40px
;
left
:
360px
;
opacity
:
1
;
}
70
%
{
top
:
130px
;
left
:
180px
;
opacity
:
1
;
}
100
%
{
top
:
160px
;
left
:
120px
;
opacity
:
0
;
}
80
%
{
top
:
180px
;
left
:
340px
;
opacity
:
1
;
}
@keyframes
cloudRight
{
0
%
{
top
:
100px
;
left
:
500px
;
opacity
:
0
;
}
20
%
{
top
:
120px
;
left
:
460px
;
opacity
:
1
;
}
80
%
{
top
:
180px
;
left
:
340px
;
opacity
:
1
;
}
100
%
{
top
:
200px
;
left
:
300px
;
opacity
:
0
;
}
100
%
{
top
:
200px
;
left
:
300px
;
opacity
:
0
;
}
}
}
.bullshit
{
position
:
relative
;
}
.bullshit
{
position
:
relative
;
float
:
left
;
width
:
300px
;
padding
:
150px
0
;
overflow
:
hidden
;
&
__oops
{
font-size
:
32px
;
font-weight
:
bold
;
line-height
:
40px
;
color
:
#1482f0
;
opacity
:
0
;
margin-bottom
:
20px
;
animation-name
:
slideUp
;
animation-duration
:
0
.5s
;
animation-fill-mode
:
forwards
;
}
&
__headline
{
font-size
:
20px
;
line-height
:
24px
;
color
:
#1482f0
;
opacity
:
0
;
margin-bottom
:
10px
;
animation-name
:
slideUp
;
animation-duration
:
0
.5s
;
animation-delay
:
0
.1s
;
animation-fill-mode
:
forwards
;
}
&
__info
{
font-size
:
13px
;
line-height
:
21px
;
color
:
grey
;
opacity
:
0
;
margin-bottom
:
30px
;
animation-name
:
slideUp
;
animation-duration
:
0
.5s
;
animation-delay
:
0
.2s
;
animation-fill-mode
:
forwards
;
}
&
__return-home
{
display
:
block
;
float
:
left
;
width
:
300px
;
padding
:
150px
0
;
overflow
:
hidden
;
&
__oops
{
font-size
:
32px
;
font-weight
:
bold
;
line-height
:
40px
;
color
:
#1482f0
;
opacity
:
0
;
margin-bottom
:
20px
;
animation-name
:
slideUp
;
animation-duration
:
0
.5s
;
animation-fill-mode
:
forwards
;
}
&
__headline
{
font-size
:
20px
;
line-height
:
24px
;
color
:
#1482f0
;
opacity
:
0
;
margin-bottom
:
10px
;
animation-name
:
slideUp
;
animation-duration
:
0
.5s
;
animation-delay
:
0
.1s
;
animation-fill-mode
:
forwards
;
}
&
__info
{
font-size
:
13px
;
line-height
:
21px
;
color
:
grey
;
opacity
:
0
;
margin-bottom
:
30px
;
animation-name
:
slideUp
;
animation-duration
:
0
.5s
;
animation-delay
:
0
.2s
;
animation-fill-mode
:
forwards
;
}
&
__return-home
{
display
:
block
;
float
:
left
;
width
:
110px
;
height
:
36px
;
background
:
#1482f0
;
border-radius
:
100px
;
text-align
:
center
;
color
:
#ffffff
;
width
:
110px
;
height
:
36px
;
background
:
#1482f0
;
border-radius
:
100px
;
text-align
:
center
;
color
:
#ffffff
;
opacity
:
0
;
font-size
:
14px
;
line-height
:
36px
;
cursor
:
pointer
;
animation-name
:
slideUp
;
animation-duration
:
0
.5s
;
animation-delay
:
0
.3s
;
animation-fill-mode
:
forwards
;
}
@keyframes
slideUp
{
0
%
{
transform
:
translateY
(
60px
);
opacity
:
0
;
font-size
:
14px
;
line-height
:
36px
;
cursor
:
pointer
;
animation-name
:
slideUp
;
animation-duration
:
0
.5s
;
animation-delay
:
0
.3s
;
animation-fill-mode
:
forwards
;
}
@keyframes
slideUp
{
0
%
{
transform
:
translateY
(
60px
);
opacity
:
0
;
}
100
%
{
transform
:
translateY
(
0
);
opacity
:
1
;
}
100
%
{
transform
:
translateY
(
0
);
opacity
:
1
;
}
}
}
}
</
style
>
src/views/example/form.vue
View file @
de992c50
...
...
@@ -120,141 +120,141 @@
</template>
<
script
>
import
Tinymce
from
'components/Tinymce'
import
Upload
from
'components/Upload/singleImage3'
import
MDinput
from
'components/MDinput'
;
import
{
validateURL
}
from
'utils/validate'
;
import
{
getArticle
}
from
'api/article'
;
import
{
userSearch
}
from
'api/remoteSearch'
;
import
Tinymce
from
'components/Tinymce'
import
Upload
from
'components/Upload/singleImage3'
import
MDinput
from
'components/MDinput'
;
import
{
validateURL
}
from
'utils/validate'
;
import
{
getArticle
}
from
'api/article'
;
import
{
userSearch
}
from
'api/remoteSearch'
;
export
default
{
name
:
'articleDetail'
,
components
:
{
Tinymce
,
MDinput
,
Upload
},
data
()
{
const
validateRequire
=
(
rule
,
value
,
callback
)
=>
{
if
(
value
===
''
)
{
export
default
{
name
:
'articleDetail'
,
components
:
{
Tinymce
,
MDinput
,
Upload
},
data
()
{
const
validateRequire
=
(
rule
,
value
,
callback
)
=>
{
if
(
value
===
''
)
{
this
.
$message
({
message
:
rule
.
field
+
'为必传项'
,
type
:
'error'
});
callback
(
null
)
}
else
{
callback
()
}
};
const
validateSourceUri
=
(
rule
,
value
,
callback
)
=>
{
if
(
value
)
{
if
(
validateURL
(
value
))
{
callback
()
}
else
{
this
.
$message
({
message
:
rule
.
field
+
'为必传项
'
,
message
:
'外链url填写不正确
'
,
type
:
'error'
});
callback
(
null
)
}
else
{
callback
()
}
};
const
validateSourceUri
=
(
rule
,
value
,
callback
)
=>
{
if
(
value
)
{
if
(
validateURL
(
value
))
{
callback
()
}
else
{
this
.
$message
({
message
:
'外链url填写不正确'
,
type
:
'error'
});
callback
(
null
)
}
}
else
{
callback
()
}
};
return
{
postForm
:
{
title
:
''
,
// 文章题目
content
:
''
,
// 文章内容
content_short
:
''
,
// 文章摘要
source_uri
:
''
,
// 文章外链
image_uri
:
''
,
// 文章图片
source_name
:
''
,
// 文章外部作者
display_time
:
undefined
,
// 前台展示时间
id
:
undefined
,
platforms
:
[
'a-platform'
]
},
fetchSuccess
:
true
,
loading
:
false
,
userLIstOptions
:
[],
platformsOptions
:
[
}
else
{
callback
()
}
};
return
{
postForm
:
{
title
:
''
,
// 文章题目
content
:
''
,
// 文章内容
content_short
:
''
,
// 文章摘要
source_uri
:
''
,
// 文章外链
image_uri
:
''
,
// 文章图片
source_name
:
''
,
// 文章外部作者
display_time
:
undefined
,
// 前台展示时间
id
:
undefined
,
platforms
:
[
'a-platform'
]
},
fetchSuccess
:
true
,
loading
:
false
,
userLIstOptions
:
[],
platformsOptions
:
[
{
key
:
'a-platform'
,
name
:
'a-platform'
},
{
key
:
'b-platform'
,
name
:
'b-platform'
},
{
key
:
'c-platform'
,
name
:
'c-platform'
}
],
rules
:
{
image_uri
:
[{
validator
:
validateRequire
}],
title
:
[{
validator
:
validateRequire
}],
content
:
[{
validator
:
validateRequire
}],
source_uri
:
[{
validator
:
validateSourceUri
,
trigger
:
'blur'
}]
}
],
rules
:
{
image_uri
:
[{
validator
:
validateRequire
}],
title
:
[{
validator
:
validateRequire
}],
content
:
[{
validator
:
validateRequire
}],
source_uri
:
[{
validator
:
validateSourceUri
,
trigger
:
'blur'
}]
}
}
},
computed
:
{
contentShortLength
()
{
return
this
.
postForm
.
content_short
.
length
},
computed
:
{
contentShortLength
()
{
return
this
.
postForm
.
content_short
.
length
},
isEdit
()
{
return
this
.
$route
.
meta
.
isEdit
// 根据meta判断
isEdit
()
{
return
this
.
$route
.
meta
.
isEdit
// 根据meta判断
// return this.$route.path.indexOf('edit') !== -1 // 根据路由判断
}
},
created
()
{
if
(
this
.
isEdit
)
{
this
.
fetchData
();
}
}
},
created
()
{
if
(
this
.
isEdit
)
{
this
.
fetchData
();
}
},
methods
:
{
fetchData
()
{
getArticle
().
then
(
response
=>
{
this
.
postForm
=
response
.
data
;
}).
catch
(
err
=>
{
this
.
fetchSuccess
=
false
;
console
.
log
(
err
);
});
},
methods
:
{
fetchData
()
{
getArticle
().
then
(
response
=>
{
this
.
postForm
=
response
.
data
;
}).
catch
(
err
=>
{
this
.
fetchSuccess
=
false
;
console
.
log
(
err
);
});
},
submitForm
()
{
this
.
postForm
.
display_time
=
parseInt
(
this
.
display_time
/
1000
);
console
.
log
(
this
.
postForm
)
this
.
$refs
.
postForm
.
validate
(
valid
=>
{
if
(
valid
)
{
this
.
loading
=
true
;
this
.
$notify
({
title
:
'成功'
,
message
:
'发布文章成功'
,
type
:
'success'
,
duration
:
2000
});
this
.
postForm
.
status
=
'published'
;
this
.
loading
=
false
;
}
else
{
console
.
log
(
'error submit!!'
);
return
false
;
}
});
},
draftForm
()
{
if
(
this
.
postForm
.
content
.
length
===
0
||
this
.
postForm
.
title
.
length
===
0
)
{
this
.
$message
({
message
:
'请填写必要的标题和内容'
,
type
:
'warning'
submitForm
()
{
this
.
postForm
.
display_time
=
parseInt
(
this
.
display_time
/
1000
);
console
.
log
(
this
.
postForm
)
this
.
$refs
.
postForm
.
validate
(
valid
=>
{
if
(
valid
)
{
this
.
loading
=
true
;
this
.
$notify
({
title
:
'成功'
,
message
:
'发布文章成功'
,
type
:
'success'
,
duration
:
2000
});
return
;
this
.
postForm
.
status
=
'published'
;
this
.
loading
=
false
;
}
else
{
console
.
log
(
'error submit!!'
);
return
false
;
}
});
},
draftForm
()
{
if
(
this
.
postForm
.
content
.
length
===
0
||
this
.
postForm
.
title
.
length
===
0
)
{
this
.
$message
({
message
:
'保存成功'
,
type
:
'success'
,
showClose
:
true
,
duration
:
1000
message
:
'请填写必要的标题和内容'
,
type
:
'warning'
});
this
.
postForm
.
status
=
'draft'
;
},
getRemoteUserList
(
query
)
{
userSearch
(
query
).
then
(
response
=>
{
if
(
!
response
.
data
.
items
)
return
;
console
.
log
(
response
)
this
.
userLIstOptions
=
response
.
data
.
items
.
map
(
v
=>
({
key
:
v
.
name
}));
})
return
;
}
this
.
$message
({
message
:
'保存成功'
,
type
:
'success'
,
showClose
:
true
,
duration
:
1000
});
this
.
postForm
.
status
=
'draft'
;
},
getRemoteUserList
(
query
)
{
userSearch
(
query
).
then
(
response
=>
{
if
(
!
response
.
data
.
items
)
return
;
console
.
log
(
response
)
this
.
userLIstOptions
=
response
.
data
.
items
.
map
(
v
=>
({
key
:
v
.
name
}));
})
}
}
}
</
script
>
<
style
rel=
"stylesheet/scss"
lang=
"scss"
scoped
>
@import
"src/styles/mixin.scss"
;
...
...
src/views/example/table/dragTable.vue
View file @
de992c50
...
...
@@ -60,64 +60,64 @@
<
/template
>
<
script
>
import
{
fetchList
}
from
'api/article_table'
;
import
Sortable
from
'sortablejs'
import
{
fetchList
}
from
'api/article_table'
;
import
Sortable
from
'sortablejs'
export
default
{
name
:
'drag-table_demo'
,
data
()
{
return
{
list
:
null
,
total
:
null
,
listLoading
:
true
,
listQuery
:
{
page
:
1
,
limit
:
10
}
,
sortable
:
null
,
olderList
:
[],
newList
:
[]
}
}
,
created
()
{
this
.
getList
();
}
,
filters
:
{
statusFilter
(
status
)
{
const
statusMap
=
{
published
:
'success'
,
draft
:
'gray'
,
deleted
:
'danger'
}
;
return
statusMap
[
status
]
}
}
,
methods
:
{
getList
()
{
this
.
listLoading
=
true
;
fetchList
(
this
.
listQuery
).
then
(
response
=>
{
this
.
list
=
response
.
data
.
items
;
this
.
total
=
response
.
data
.
total
;
this
.
listLoading
=
false
;
this
.
olderList
=
this
.
list
.
map
(
v
=>
v
.
id
);
this
.
newList
=
this
.
olderList
.
slice
();
this
.
$nextTick
(()
=>
{
this
.
setSort
()
}
)
}
)
export
default
{
name
:
'drag-table_demo'
,
data
()
{
return
{
list
:
null
,
total
:
null
,
listLoading
:
true
,
listQuery
:
{
page
:
1
,
limit
:
10
}
,
setSort
()
{
const
el
=
document
.
querySelectorAll
(
'.el-table__body-wrapper > table > tbody'
)[
0
];
this
.
sortable
=
Sortable
.
create
(
el
,
{
sortable
:
null
,
olderList
:
[],
newList
:
[]
}
}
,
created
()
{
this
.
getList
();
}
,
filters
:
{
statusFilter
(
status
)
{
const
statusMap
=
{
published
:
'success'
,
draft
:
'gray'
,
deleted
:
'danger'
}
;
return
statusMap
[
status
]
}
}
,
methods
:
{
getList
()
{
this
.
listLoading
=
true
;
fetchList
(
this
.
listQuery
).
then
(
response
=>
{
this
.
list
=
response
.
data
.
items
;
this
.
total
=
response
.
data
.
total
;
this
.
listLoading
=
false
;
this
.
olderList
=
this
.
list
.
map
(
v
=>
v
.
id
);
this
.
newList
=
this
.
olderList
.
slice
();
this
.
$nextTick
(()
=>
{
this
.
setSort
()
}
)
}
)
}
,
setSort
()
{
const
el
=
document
.
querySelectorAll
(
'.el-table__body-wrapper > table > tbody'
)[
0
];
this
.
sortable
=
Sortable
.
create
(
el
,
{
// handle: '.drag-handler',
onEnd
:
evt
=>
{
const
tempIndex
=
this
.
newList
.
splice
(
evt
.
oldIndex
,
1
)[
0
];
this
.
newList
.
splice
(
evt
.
newIndex
,
0
,
tempIndex
);
}
}
);
}
onEnd
:
evt
=>
{
const
tempIndex
=
this
.
newList
.
splice
(
evt
.
oldIndex
,
1
)[
0
];
this
.
newList
.
splice
(
evt
.
newIndex
,
0
,
tempIndex
);
}
}
);
}
}
}
<
/script
>
<
style
>
...
...
src/views/example/table/dynamictable.vue
View file @
de992c50
<
template
>
<div
class=
"app-container"
>
<div
style=
'margin:0 0 5px 20px'
>
固定表头 按照表头顺序排序
</div>
<fixed-thead
/
>
<fixed-thead
></fixed-thead
>
<div
style=
'margin:30px 0 5px 20px'
>
不固定表头 按照点击顺序排序
</div>
<unfixed-thead
/
>
<unfixed-thead
></unfixed-thead
>
</div>
</
template
>
...
...
src/views/example/table/inlineEditTable.vue
View file @
de992c50
...
...
@@ -23,7 +23,7 @@
<
el
-
table
-
column
width
=
"100px"
label
=
"重要性"
>
<
template
scope
=
"scope"
>
<
icon
-
svg
v
-
for
=
"n in +scope.row.importance"
icon
-
class
=
"wujiaoxing"
class
=
"meta-item__icon"
:
key
=
"n"
><
/icon-svg
>
<
icon
-
svg
v
-
for
=
"n in +scope.row.importance"
icon
-
class
=
"wujiaoxing"
class
=
"meta-item__icon"
:
key
=
"n"
><
/icon-svg
>
<
/template
>
<
/el-table-column
>
...
...
@@ -52,44 +52,44 @@
<
/template
>
<
script
>
import
{
fetchList
}
from
'api/article_table'
;
import
{
fetchList
}
from
'api/article_table'
;
export
default
{
name
:
'inline_edit-table_demo'
,
data
()
{
return
{
list
:
null
,
listLoading
:
true
,
listQuery
:
{
page
:
1
,
limit
:
10
}
}
}
,
created
()
{
this
.
getList
();
}
,
filters
:
{
statusFilter
(
status
)
{
const
statusMap
=
{
published
:
'success'
,
draft
:
'gray'
,
deleted
:
'danger'
}
;
return
statusMap
[
status
]
}
}
,
methods
:
{
getList
()
{
this
.
listLoading
=
true
;
fetchList
(
this
.
listQuery
).
then
(
response
=>
{
this
.
list
=
response
.
data
.
items
.
map
(
v
=>
{
v
.
edit
=
false
;
return
v
}
);
this
.
listLoading
=
false
;
}
)
export
default
{
name
:
'inline_edit-table_demo'
,
data
()
{
return
{
list
:
null
,
listLoading
:
true
,
listQuery
:
{
page
:
1
,
limit
:
10
}
}
}
,
created
()
{
this
.
getList
();
}
,
filters
:
{
statusFilter
(
status
)
{
const
statusMap
=
{
published
:
'success'
,
draft
:
'gray'
,
deleted
:
'danger'
}
;
return
statusMap
[
status
]
}
}
,
methods
:
{
getList
()
{
this
.
listLoading
=
true
;
fetchList
(
this
.
listQuery
).
then
(
response
=>
{
this
.
list
=
response
.
data
.
items
.
map
(
v
=>
{
v
.
edit
=
false
;
return
v
}
);
this
.
listLoading
=
false
;
}
)
}
}
}
<
/script
>
src/views/example/table/table.vue
View file @
de992c50
...
...
@@ -60,7 +60,7 @@
<
el
-
table
-
column
width
=
"80px"
label
=
"重要性"
>
<
template
scope
=
"scope"
>
<
icon
-
svg
v
-
for
=
"n in +scope.row.importance"
icon
-
class
=
"wujiaoxing"
class
=
"meta-item__icon"
:
key
=
"n"
><
/icon-svg
>
<
icon
-
svg
v
-
for
=
"n in +scope.row.importance"
icon
-
class
=
"wujiaoxing"
class
=
"meta-item__icon"
:
key
=
"n"
><
/icon-svg
>
<
/template
>
<
/el-table-column
>
...
...
@@ -150,199 +150,199 @@
<
/template
>
<
script
>
import
{
fetchList
,
fetchPv
}
from
'api/article_table'
;
import
{
parseTime
}
from
'utils'
;
import
{
fetchList
,
fetchPv
}
from
'api/article_table'
;
import
{
parseTime
}
from
'utils'
;
const
calendarTypeOptions
=
[
const
calendarTypeOptions
=
[
{
key
:
'CN'
,
display_name
:
'中国'
}
,
{
key
:
'US'
,
display_name
:
'美国'
}
,
{
key
:
'JP'
,
display_name
:
'日本'
}
,
{
key
:
'EU'
,
display_name
:
'欧元区'
}
];
];
// arr to obj
const
calendarTypeKeyValue
=
calendarTypeOptions
.
reduce
((
acc
,
cur
)
=>
{
acc
[
cur
.
key
]
=
cur
.
display_name
;
return
acc
}
,
{
}
);
// arr to obj
const
calendarTypeKeyValue
=
calendarTypeOptions
.
reduce
((
acc
,
cur
)
=>
{
acc
[
cur
.
key
]
=
cur
.
display_name
;
return
acc
}
,
{
}
);
export
default
{
name
:
'table_demo'
,
data
()
{
return
{
list
:
null
,
total
:
null
,
listLoading
:
true
,
listQuery
:
{
page
:
1
,
limit
:
20
,
importance
:
undefined
,
title
:
undefined
,
type
:
undefined
,
sort
:
'+id'
}
,
temp
:
{
id
:
undefined
,
importance
:
0
,
remark
:
''
,
timestamp
:
0
,
title
:
''
,
type
:
''
,
status
:
'published'
}
,
importanceOptions
:
[
1
,
2
,
3
],
calendarTypeOptions
,
sortOptions
:
[{
label
:
'按ID升序列'
,
key
:
'+id'
}
,
{
label
:
'按ID降序'
,
key
:
'-id'
}
],
statusOptions
:
[
'published'
,
'draft'
,
'deleted'
],
dialogFormVisible
:
false
,
dialogStatus
:
''
,
textMap
:
{
update
:
'编辑'
,
create
:
'创建'
}
,
dialogPvVisible
:
false
,
pvData
:
[],
showAuditor
:
false
,
tableKey
:
0
}
export
default
{
name
:
'table_demo'
,
data
()
{
return
{
list
:
null
,
total
:
null
,
listLoading
:
true
,
listQuery
:
{
page
:
1
,
limit
:
20
,
importance
:
undefined
,
title
:
undefined
,
type
:
undefined
,
sort
:
'+id'
}
,
temp
:
{
id
:
undefined
,
importance
:
0
,
remark
:
''
,
timestamp
:
0
,
title
:
''
,
type
:
''
,
status
:
'published'
}
,
importanceOptions
:
[
1
,
2
,
3
],
calendarTypeOptions
,
sortOptions
:
[{
label
:
'按ID升序列'
,
key
:
'+id'
}
,
{
label
:
'按ID降序'
,
key
:
'-id'
}
],
statusOptions
:
[
'published'
,
'draft'
,
'deleted'
],
dialogFormVisible
:
false
,
dialogStatus
:
''
,
textMap
:
{
update
:
'编辑'
,
create
:
'创建'
}
,
dialogPvVisible
:
false
,
pvData
:
[],
showAuditor
:
false
,
tableKey
:
0
}
}
,
created
()
{
this
.
getList
();
}
,
filters
:
{
statusFilter
(
status
)
{
const
statusMap
=
{
published
:
'success'
,
draft
:
'gray'
,
deleted
:
'danger'
}
;
return
statusMap
[
status
]
}
,
created
()
{
typeFilter
(
type
)
{
return
calendarTypeKeyValue
[
type
]
}
}
,
methods
:
{
getList
()
{
this
.
listLoading
=
true
;
fetchList
(
this
.
listQuery
).
then
(
response
=>
{
this
.
list
=
response
.
data
.
items
;
this
.
total
=
response
.
data
.
total
;
this
.
listLoading
=
false
;
}
)
}
,
handleFilter
()
{
this
.
getList
();
}
,
filters
:
{
statusFilter
(
status
)
{
const
statusMap
=
{
published
:
'success'
,
draft
:
'gray'
,
deleted
:
'danger'
}
;
return
statusMap
[
status
]
}
,
typeFilter
(
type
)
{
return
calendarTypeKeyValue
[
type
]
handleSizeChange
(
val
)
{
this
.
listQuery
.
limit
=
val
;
this
.
getList
();
}
,
handleCurrentChange
(
val
)
{
this
.
listQuery
.
page
=
val
;
this
.
getList
();
}
,
timeFilter
(
time
)
{
if
(
!
time
[
0
])
{
this
.
listQuery
.
start
=
undefined
;
this
.
listQuery
.
end
=
undefined
;
return
;
}
this
.
listQuery
.
start
=
parseInt
(
+
time
[
0
]
/
1000
);
this
.
listQuery
.
end
=
parseInt
((
+
time
[
1
]
+
3600
*
1000
*
24
)
/
1000
);
}
,
methods
:
{
getList
()
{
this
.
listLoading
=
true
;
fetchList
(
this
.
listQuery
).
then
(
response
=>
{
this
.
list
=
response
.
data
.
items
;
this
.
total
=
response
.
data
.
total
;
this
.
listLoading
=
false
;
}
)
}
,
handleFilter
()
{
this
.
getList
();
}
,
handleSizeChange
(
val
)
{
this
.
listQuery
.
limit
=
val
;
this
.
getList
();
}
,
handleCurrentChange
(
val
)
{
this
.
listQuery
.
page
=
val
;
this
.
getList
();
}
,
timeFilter
(
time
)
{
if
(
!
time
[
0
])
{
this
.
listQuery
.
start
=
undefined
;
this
.
listQuery
.
end
=
undefined
;
return
;
}
this
.
listQuery
.
start
=
parseInt
(
+
time
[
0
]
/
1000
);
this
.
listQuery
.
end
=
parseInt
((
+
time
[
1
]
+
3600
*
1000
*
24
)
/
1000
);
}
,
handleModifyStatus
(
row
,
status
)
{
this
.
$message
({
message
:
'操作成功'
,
type
:
'success'
}
);
row
.
status
=
status
;
}
,
handleCreate
()
{
this
.
resetTemp
();
this
.
dialogStatus
=
'create'
;
this
.
dialogFormVisible
=
true
;
}
,
handleUpdate
(
row
)
{
this
.
temp
=
Object
.
assign
({
}
,
row
);
this
.
dialogStatus
=
'update'
;
this
.
dialogFormVisible
=
true
;
}
,
handleDelete
(
row
)
{
this
.
$notify
({
title
:
'成功'
,
message
:
'删除成功'
,
type
:
'success'
,
duration
:
2000
}
);
const
index
=
this
.
list
.
indexOf
(
row
);
this
.
list
.
splice
(
index
,
1
);
}
,
create
()
{
this
.
temp
.
id
=
parseInt
(
Math
.
random
()
*
100
)
+
1024
;
this
.
temp
.
timestamp
=
+
new
Date
();
this
.
temp
.
author
=
'原创作者'
;
this
.
list
.
unshift
(
this
.
temp
);
this
.
dialogFormVisible
=
false
;
this
.
$notify
({
title
:
'成功'
,
message
:
'创建成功'
,
type
:
'success'
,
duration
:
2000
}
);
}
,
update
()
{
this
.
temp
.
timestamp
=
+
this
.
temp
.
timestamp
;
for
(
const
v
of
this
.
list
)
{
if
(
v
.
id
===
this
.
temp
.
id
)
{
const
index
=
this
.
list
.
indexOf
(
v
);
this
.
list
.
splice
(
index
,
1
,
this
.
temp
);
break
;
}
handleModifyStatus
(
row
,
status
)
{
this
.
$message
({
message
:
'操作成功'
,
type
:
'success'
}
);
row
.
status
=
status
;
}
,
handleCreate
()
{
this
.
resetTemp
();
this
.
dialogStatus
=
'create'
;
this
.
dialogFormVisible
=
true
;
}
,
handleUpdate
(
row
)
{
this
.
temp
=
Object
.
assign
({
}
,
row
);
this
.
dialogStatus
=
'update'
;
this
.
dialogFormVisible
=
true
;
}
,
handleDelete
(
row
)
{
this
.
$notify
({
title
:
'成功'
,
message
:
'删除成功'
,
type
:
'success'
,
duration
:
2000
}
);
const
index
=
this
.
list
.
indexOf
(
row
);
this
.
list
.
splice
(
index
,
1
);
}
,
create
()
{
this
.
temp
.
id
=
parseInt
(
Math
.
random
()
*
100
)
+
1024
;
this
.
temp
.
timestamp
=
+
new
Date
();
this
.
temp
.
author
=
'原创作者'
;
this
.
list
.
unshift
(
this
.
temp
);
this
.
dialogFormVisible
=
false
;
this
.
$notify
({
title
:
'成功'
,
message
:
'创建成功'
,
type
:
'success'
,
duration
:
2000
}
);
}
,
update
()
{
this
.
temp
.
timestamp
=
+
this
.
temp
.
timestamp
;
for
(
const
v
of
this
.
list
)
{
if
(
v
.
id
===
this
.
temp
.
id
)
{
const
index
=
this
.
list
.
indexOf
(
v
);
this
.
list
.
splice
(
index
,
1
,
this
.
temp
);
break
;
}
this
.
dialogFormVisible
=
false
;
this
.
$notify
({
title
:
'成功'
,
message
:
'更新成功'
,
type
:
'success'
,
duration
:
2000
}
);
}
,
resetTemp
()
{
this
.
temp
=
{
id
:
undefined
,
importance
:
0
,
remark
:
''
,
timestamp
:
0
,
title
:
''
,
status
:
'published'
,
type
:
''
}
;
}
,
handleFetchPv
(
pv
)
{
fetchPv
(
pv
).
then
(
response
=>
{
this
.
pvData
=
response
.
data
.
pvData
;
this
.
dialogPvVisible
=
true
;
}
)
}
,
handleDownload
()
{
require
.
ensure
([],
()
=>
{
const
{
export_json_to_excel
}
=
require
(
'vendor/Export2Excel'
);
const
tHeader
=
[
'时间'
,
'地区'
,
'类型'
,
'标题'
,
'重要性'
];
const
filterVal
=
[
'timestamp'
,
'province'
,
'type'
,
'title'
,
'importance'
];
const
data
=
this
.
formatJson
(
filterVal
,
this
.
list
);
export_json_to_excel
(
tHeader
,
data
,
'table数据'
);
}
)
}
,
formatJson
(
filterVal
,
jsonData
)
{
return
jsonData
.
map
(
v
=>
filterVal
.
map
(
j
=>
{
if
(
j
===
'timestamp'
)
{
return
parseTime
(
v
[
j
])
}
else
{
return
v
[
j
]
}
}
))
}
this
.
dialogFormVisible
=
false
;
this
.
$notify
({
title
:
'成功'
,
message
:
'更新成功'
,
type
:
'success'
,
duration
:
2000
}
);
}
,
resetTemp
()
{
this
.
temp
=
{
id
:
undefined
,
importance
:
0
,
remark
:
''
,
timestamp
:
0
,
title
:
''
,
status
:
'published'
,
type
:
''
}
;
}
,
handleFetchPv
(
pv
)
{
fetchPv
(
pv
).
then
(
response
=>
{
this
.
pvData
=
response
.
data
.
pvData
;
this
.
dialogPvVisible
=
true
;
}
)
}
,
handleDownload
()
{
require
.
ensure
([],
()
=>
{
const
{
export_json_to_excel
}
=
require
(
'vendor/Export2Excel'
);
const
tHeader
=
[
'时间'
,
'地区'
,
'类型'
,
'标题'
,
'重要性'
];
const
filterVal
=
[
'timestamp'
,
'province'
,
'type'
,
'title'
,
'importance'
];
const
data
=
this
.
formatJson
(
filterVal
,
this
.
list
);
export_json_to_excel
(
tHeader
,
data
,
'table数据'
);
}
)
}
,
formatJson
(
filterVal
,
jsonData
)
{
return
jsonData
.
map
(
v
=>
filterVal
.
map
(
j
=>
{
if
(
j
===
'timestamp'
)
{
return
parseTime
(
v
[
j
])
}
else
{
return
v
[
j
]
}
}
))
}
}
}
<
/script
>
src/views/excel/index.vue
View file @
de992c50
...
...
@@ -34,38 +34,41 @@
</template>
<
script
>
import
{
getList
}
from
'api/article'
;
export
default
{
data
()
{
return
{
list
:
null
,
listLoading
:
true
}
},
created
()
{
this
.
fetchData
();
},
methods
:
{
fetchData
()
{
this
.
listLoading
=
true
;
getList
(
this
.
listQuery
).
then
(
response
=>
{
this
.
list
=
response
.
data
;
this
.
listLoading
=
false
;
})
import
{
getList
}
from
'api/article'
;
export
default
{
data
()
{
return
{
list
:
null
,
listLoading
:
true
}
},
handleDownload
()
{
require
.
ensure
([],
()
=>
{
const
{
export_json_to_excel
}
=
require
(
'vendor/Export2Excel'
);
const
tHeader
=
[
'序号'
,
'文章标题'
,
'作者'
,
'阅读数'
,
'发布时间'
];
const
filterVal
=
[
'id'
,
'title'
,
'author'
,
'pageviews'
,
'display_time'
];
const
list
=
this
.
list
;
const
data
=
this
.
formatJson
(
filterVal
,
list
);
export_json_to_excel
(
tHeader
,
data
,
'列表excel'
);
})
created
()
{
this
.
fetchData
();
},
formatJson
(
filterVal
,
jsonData
)
{
return
jsonData
.
map
(
v
=>
filterVal
.
map
(
j
=>
v
[
j
]))
methods
:
{
fetchData
()
{
this
.
listLoading
=
true
;
getList
(
this
.
listQuery
).
then
(
response
=>
{
this
.
list
=
response
.
data
;
this
.
listLoading
=
false
;
})
},
handleDownload
()
{
require
.
ensure
([],
()
=>
{
const
{
export_json_to_excel
}
=
require
(
'vendor/Export2Excel'
);
const
tHeader
=
[
'序号'
,
'文章标题'
,
'作者'
,
'阅读数'
,
'发布时间'
];
const
filterVal
=
[
'id'
,
'title'
,
'author'
,
'pageviews'
,
'display_time'
];
const
list
=
this
.
list
;
const
data
=
this
.
formatJson
(
filterVal
,
list
);
export_json_to_excel
(
tHeader
,
data
,
'列表excel'
);
})
},
formatJson
(
filterVal
,
jsonData
)
{
return
jsonData
.
map
(
v
=>
filterVal
.
map
(
j
=>
v
[
j
]))
}
}
}
};
};
</
script
>
src/views/introduction/index.vue
View file @
de992c50
...
...
@@ -12,7 +12,7 @@
<li><a
target=
'_blank'
href=
"https://juejin.im/post/593121aa0ce4630057f70d35"
>
手摸手,带你用 vue 撸后台 系列三 (实战篇)
</a></li>
<li><a
target=
'_blank'
href=
"https://segmentfault.com/a/1190000009090836"
>
手摸手,带你封装一个vue component
</a></li>
</ul>
</code>
</code>
</div>
</div>
</
template
>
...
...
src/views/layout/AppMain.vue
View file @
de992c50
<
template
>
<section
class=
"app-main"
style=
"min-height: 100%"
>
<transition
name=
"fade"
mode=
"out-in"
>
<router-view
:key=
"key"
></router-view>
</transition>
</section>
<section
class=
"app-main"
style=
"min-height: 100%"
>
<transition
name=
"fade"
mode=
"out-in"
>
<router-view
:key=
"key"
></router-view>
</transition>
</section>
</
template
>
<
script
>
export
default
{
name
:
'AppMain'
,
computed
:
{
key
()
{
return
this
.
$route
.
name
!==
undefined
?
this
.
$route
.
name
+
+
new
Date
()
:
this
.
$route
+
+
new
Date
()
}
}
export
default
{
name
:
'AppMain'
,
computed
:
{
key
()
{
return
this
.
$route
.
name
!==
undefined
?
this
.
$route
.
name
+
+
new
Date
()
:
this
.
$route
+
+
new
Date
()
}
}
}
</
script
>
src/views/layout/Layout.vue
View file @
de992c50
<
template
>
<div
class=
"app-wrapper"
:class=
"
{hideSidebar:!sidebar.opened}">
<div
class=
"sidebar-wrapper"
>
<Sidebar
class=
"sidebar-container"
/
>
</div>
<div
class=
"main-container"
>
<Navbar/
>
<App-main/
>
</div>
</div>
<div
class=
"app-wrapper"
:class=
"
{hideSidebar:!sidebar.opened}">
<div
class=
"sidebar-wrapper"
>
<sidebar
class=
"sidebar-container"
></sidebar
>
</div>
<div
class=
"main-container"
>
<navbar></navbar
>
<app-main></app-main
>
</div>
</div>
</
template
>
<
script
>
import
{
Navbar
,
Sidebar
,
AppMain
}
from
'views/layout'
;
import
{
Navbar
,
Sidebar
,
AppMain
}
from
'views/layout'
;
export
default
{
name
:
'layout'
,
components
:
{
Navbar
,
Sidebar
,
AppMain
},
computed
:
{
sidebar
()
{
return
this
.
$store
.
state
.
app
.
sidebar
;
}
export
default
{
name
:
'layout'
,
components
:
{
Navbar
,
Sidebar
,
AppMain
},
computed
:
{
sidebar
()
{
return
this
.
$store
.
state
.
app
.
sidebar
;
}
}
}
</
script
>
<
style
rel=
"stylesheet/scss"
lang=
"scss"
scoped
>
@import
"src/styles/mixin.scss"
;
.app-wrapper
{
@include
clearfix
;
position
:
relative
;
height
:
100%
;
width
:
100%
;
&
.hideSidebar
{
.sidebar-wrapper
{
transform
:
translate
(
-140px
,
0
);
.sidebar-container
{
transform
:
translate
(
132px
,
0
);
}
&
:hover
{
transform
:
translate
(
0
,
0
);
.sidebar-container
{
transform
:
translate
(
0
,
0
);
}
}
}
.main-container
{
margin-left
:
40px
;
}
}
.sidebar-wrapper
{
width
:
180px
;
position
:
fixed
;
top
:
0
;
bottom
:
0
;
left
:
0
;
z-index
:
1001
;
overflow
:
hidden
;
transition
:
all
.28s
ease-out
;
}
.sidebar-container
{
transition
:
all
.28s
ease-out
;
position
:
absolute
;
top
:
0
;
bottom
:
0
;
left
:
0
;
right
:
-17px
;
overflow-y
:
scroll
;
}
.main-container
{
min-height
:
100%
;
transition
:
all
.28s
ease-out
;
margin-left
:
180px
;
}
}
@import
"src/styles/mixin.scss"
;
.app-wrapper
{
@include
clearfix
;
position
:
relative
;
height
:
100%
;
width
:
100%
;
&
.hideSidebar
{
.sidebar-wrapper
{
transform
:
translate
(
-140px
,
0
);
.sidebar-container
{
transform
:
translate
(
132px
,
0
);
}
&
:hover
{
transform
:
translate
(
0
,
0
);
.sidebar-container
{
transform
:
translate
(
0
,
0
);
}
}
}
.main-container
{
margin-left
:
40px
;
}
}
.sidebar-wrapper
{
width
:
180px
;
position
:
fixed
;
top
:
0
;
bottom
:
0
;
left
:
0
;
z-index
:
1001
;
overflow
:
hidden
;
transition
:
all
.28s
ease-out
;
}
.sidebar-container
{
transition
:
all
.28s
ease-out
;
position
:
absolute
;
top
:
0
;
bottom
:
0
;
left
:
0
;
right
:
-17px
;
overflow-y
:
scroll
;
}
.main-container
{
min-height
:
100%
;
transition
:
all
.28s
ease-out
;
margin-left
:
180px
;
}
}
</
style
>
src/views/layout/Levelbar.vue
View file @
de992c50
...
...
@@ -8,42 +8,42 @@
</
template
>
<
script
>
export
default
{
created
()
{
this
.
getBreadcrumb
()
},
data
()
{
return
{
levelList
:
null
}
},
methods
:
{
getBreadcrumb
()
{
let
matched
=
this
.
$route
.
matched
.
filter
(
item
=>
item
.
name
);
const
first
=
matched
[
0
];
if
(
first
&&
(
first
.
name
!==
'首页'
||
first
.
path
!==
''
))
{
matched
=
[{
name
:
'首页'
,
path
:
'/'
}].
concat
(
matched
)
}
this
.
levelList
=
matched
;
}
},
watch
:
{
$route
()
{
this
.
getBreadcrumb
();
export
default
{
created
()
{
this
.
getBreadcrumb
()
},
data
()
{
return
{
levelList
:
null
}
},
methods
:
{
getBreadcrumb
()
{
let
matched
=
this
.
$route
.
matched
.
filter
(
item
=>
item
.
name
);
const
first
=
matched
[
0
];
if
(
first
&&
(
first
.
name
!==
'首页'
||
first
.
path
!==
''
))
{
matched
=
[{
name
:
'首页'
,
path
:
'/'
}].
concat
(
matched
)
}
this
.
levelList
=
matched
;
}
},
watch
:
{
$route
()
{
this
.
getBreadcrumb
();
}
}
}
</
script
>
<
style
rel=
"stylesheet/scss"
lang=
"scss"
scoped
>
.app-levelbar.el-breadcrumb
{
display
:
inline-block
;
font-size
:
14px
;
line-height
:
50px
;
margin-left
:
10px
;
.no-redirect
{
color
:
#97a8be
;
cursor
:text
;
}
.app-levelbar.el-breadcrumb
{
display
:
inline-block
;
font-size
:
14px
;
line-height
:
50px
;
margin-left
:
10px
;
.no-redirect
{
color
:
#97a8be
;
cursor
:
text
;
}
}
</
style
>
src/views/layout/Navbar.vue
View file @
de992c50
<
template
>
<el-menu
class=
"navbar"
mode=
"horizontal"
>
<hamburger
class=
"hamburger-container"
:toggleClick=
"toggleSideBar"
:isActive=
"sidebar.opened"
></hamburger>
<levelbar></levelbar>
<tabs-view></tabs-view>
<error-log
v-if=
"log.length>0"
class=
"errLog-container"
:logsList=
"log"
></error-log>
<screenfull
class=
'screenfull'
></screenfull>
<el-dropdown
class=
"avatar-container"
trigger=
"click"
>
<div
class=
"avatar-wrapper"
>
<img
class=
"user-avatar"
:src=
"avatar+'?imageView2/1/w/80/h/80'"
>
<i
class=
"el-icon-caret-bottom"
></i>
</div>
<el-dropdown-menu
class=
"user-dropdown"
slot=
"dropdown"
>
<router-link
class=
'inlineBlock'
to=
"/"
>
<el-dropdown-item>
首页
</el-dropdown-item>
</router-link>
<a
target=
'_blank'
href=
"https://github.com/PanJiaChen/vue-element-admin/"
>
<el-dropdown-item>
项目地址
</el-dropdown-item>
</a>
<el-dropdown-item
divided
><span
@
click=
"logout"
style=
"display:block;"
>
退出登录
</span></el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</el-menu>
<el-menu
class=
"navbar"
mode=
"horizontal"
>
<hamburger
class=
"hamburger-container"
:toggleClick=
"toggleSideBar"
:isActive=
"sidebar.opened"
></hamburger>
<levelbar></levelbar>
<tabs-view></tabs-view>
<error-log
v-if=
"log.length>0"
class=
"errLog-container"
:logsList=
"log"
></error-log>
<screenfull
class=
'screenfull'
></screenfull>
<el-dropdown
class=
"avatar-container"
trigger=
"click"
>
<div
class=
"avatar-wrapper"
>
<img
class=
"user-avatar"
:src=
"avatar+'?imageView2/1/w/80/h/80'"
>
<i
class=
"el-icon-caret-bottom"
></i>
</div>
<el-dropdown-menu
class=
"user-dropdown"
slot=
"dropdown"
>
<router-link
class=
'inlineBlock'
to=
"/"
>
<el-dropdown-item>
首页
</el-dropdown-item>
</router-link>
<a
target=
'_blank'
href=
"https://github.com/PanJiaChen/vue-element-admin/"
>
<el-dropdown-item>
项目地址
</el-dropdown-item>
</a>
<el-dropdown-item
divided
><span
@
click=
"logout"
style=
"display:block;"
>
退出登录
</span></el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</el-menu>
</
template
>
<
script
>
import
{
mapGetters
}
from
'vuex'
;
import
Levelbar
from
'./Levelbar'
;
import
TabsView
from
'./TabsView'
;
import
Hamburger
from
'components/Hamburger'
;
import
Screenfull
from
'components/Screenfull'
;
import
ErrorLog
from
'components/ErrLog'
;
import
errLogStore
from
'store/errLog'
;
import
{
mapGetters
}
from
'vuex'
;
import
Levelbar
from
'./Levelbar'
;
import
TabsView
from
'./TabsView'
;
import
Hamburger
from
'components/Hamburger'
;
import
Screenfull
from
'components/Screenfull'
;
import
ErrorLog
from
'components/ErrLog'
;
import
errLogStore
from
'store/errLog'
;
export
default
{
components
:
{
Levelbar
,
TabsView
,
Hamburger
,
ErrorLog
,
Screenfull
},
data
()
{
return
{
log
:
errLogStore
.
state
.
errLog
}
},
computed
:
{
...
mapGetters
([
'sidebar'
,
'name'
,
'avatar'
])
export
default
{
components
:
{
Levelbar
,
TabsView
,
Hamburger
,
ErrorLog
,
Screenfull
},
data
()
{
return
{
log
:
errLogStore
.
state
.
errLog
}
},
computed
:
{
...
mapGetters
([
'sidebar'
,
'name'
,
'avatar'
])
},
methods
:
{
toggleSideBar
()
{
this
.
$store
.
dispatch
(
'ToggleSideBar'
)
},
methods
:
{
toggleSideBar
()
{
this
.
$store
.
dispatch
(
'ToggleSideBar'
)
},
logout
()
{
this
.
$store
.
dispatch
(
'LogOut'
).
then
(()
=>
{
location
.
reload
();
// 为了重新实例化vue-router对象 避免bug
});
}
logout
()
{
this
.
$store
.
dispatch
(
'LogOut'
).
then
(()
=>
{
location
.
reload
();
// 为了重新实例化vue-router对象 避免bug
});
}
}
}
</
script
>
<
style
rel=
"stylesheet/scss"
lang=
"scss"
scoped
>
.navbar
{
height
:
50px
;
line-height
:
50px
;
border-radius
:
0px
!
important
;
.hamburger-container
{
line-height
:
58px
;
height
:
50px
;
float
:
left
;
padding
:
0
10px
;
}
.errLog-container
{
display
:
inline-block
;
position
:
absolute
;
right
:
150px
;
}
.screenfull
{
position
:
absolute
;
right
:
90px
;
top
:
16px
;
color
:
red
;
}
.avatar-container
{
height
:
50px
;
display
:
inline-block
;
position
:
absolute
;
right
:
35px
;
.avatar-wrapper
{
cursor
:
pointer
;
margin-top
:
5px
;
position
:
relative
;
.user-avatar
{
width
:
40px
;
height
:
40px
;
border-radius
:
10px
;
}
.el-icon-caret-bottom
{
position
:
absolute
;
right
:
-20px
;
top
:
25px
;
font-size
:
12px
;
}
}
}
}
.navbar
{
height
:
50px
;
line-height
:
50px
;
border-radius
:
0px
!
important
;
.hamburger-container
{
line-height
:
58px
;
height
:
50px
;
float
:
left
;
padding
:
0
10px
;
}
.errLog-container
{
display
:
inline-block
;
position
:
absolute
;
right
:
150px
;
}
.screenfull
{
position
:
absolute
;
right
:
90px
;
top
:
16px
;
color
:
red
;
}
.avatar-container
{
height
:
50px
;
display
:
inline-block
;
position
:
absolute
;
right
:
35px
;
.avatar-wrapper
{
cursor
:
pointer
;
margin-top
:
5px
;
position
:
relative
;
.user-avatar
{
width
:
40px
;
height
:
40px
;
border-radius
:
10px
;
}
.el-icon-caret-bottom
{
position
:
absolute
;
right
:
-20px
;
top
:
25px
;
font-size
:
12px
;
}
}
}
}
</
style
>
...
...
src/views/layout/Sidebar.vue
View file @
de992c50
<
template
>
<el-menu
mode=
"vertical"
theme=
"dark"
:default-active=
"$route.path"
>
<sidebar-item
:routes=
'permission_routers'
></sidebar-item>
</el-menu>
<el-menu
mode=
"vertical"
theme=
"dark"
:default-active=
"$route.path"
>
<sidebar-item
:routes=
'permission_routers'
></sidebar-item>
</el-menu>
</
template
>
<
script
>
import
{
mapGetters
}
from
'vuex'
;
import
SidebarItem
from
'./SidebarItem'
;
export
default
{
components
:
{
SidebarItem
},
computed
:
{
...
mapGetters
([
'permission_routers'
])
}
import
{
mapGetters
}
from
'vuex'
;
import
SidebarItem
from
'./SidebarItem'
;
export
default
{
components
:
{
SidebarItem
},
computed
:
{
...
mapGetters
([
'permission_routers'
])
}
}
</
script
>
<
style
rel=
"stylesheet/scss"
lang=
"scss"
scoped
>
.el-menu
{
min-height
:
100%
;
}
.el-menu
{
min-height
:
100%
;
}
</
style
>
src/views/layout/SidebarItem.vue
View file @
de992c50
<
template
>
<div>
<template
v-for=
"item in routes"
>
<router-link
v-if=
"!item.hidden&&item.noDropdown&&item.children.length>0"
:to=
"item.path+'/'+item.children[0].path"
>
<el-menu-item
:index=
"item.path+'/'+item.children[0].path"
>
<icon-svg
v-if=
'item.icon'
:icon-class=
"item.icon"
></icon-svg>
{{
item
.
children
[
0
].
name
}}
</el-menu-item>
</router-link>
<el-submenu
:index=
"item.name"
v-if=
"!item.noDropdown&&!item.hidden"
>
<template
slot=
"title"
>
<icon-svg
v-if=
'item.icon'
:icon-class=
"item.icon"
></icon-svg>
{{
item
.
name
}}
</
template
>
<
template
v-for=
"child in item.children"
v-if=
'!child.hidden'
>
<sidebar-item
class=
'menu-indent'
v-if=
'child.children&&child.children.length>0'
:routes=
'[child]'
>
</sidebar-item>
<router-link
v-else
class=
"menu-indent"
:to=
"item.path+'/'+child.path"
>
<el-menu-item
:index=
"item.path+'/'+child.path"
>
{{
child
.
name
}}
</el-menu-item>
</router-link>
</
template
>
</el-submenu>
</template>
</div>
<div>
<template
v-for=
"item in routes"
>
<router-link
v-if=
"!item.hidden&&item.noDropdown&&item.children.length>0"
:to=
"item.path+'/'+item.children[0].path"
>
<el-menu-item
:index=
"item.path+'/'+item.children[0].path"
>
<icon-svg
v-if=
'item.icon'
:icon-class=
"item.icon"
></icon-svg>
{{
item
.
children
[
0
].
name
}}
</el-menu-item>
</router-link>
<el-submenu
:index=
"item.name"
v-if=
"!item.noDropdown&&!item.hidden"
>
<template
slot=
"title"
>
<icon-svg
v-if=
'item.icon'
:icon-class=
"item.icon"
></icon-svg>
{{
item
.
name
}}
</
template
>
<
template
v-for=
"child in item.children"
v-if=
'!child.hidden'
>
<sidebar-item
class=
'menu-indent'
v-if=
'child.children&&child.children.length>0'
:routes=
'[child]'
>
</sidebar-item>
<router-link
v-else
class=
"menu-indent"
:to=
"item.path+'/'+child.path"
>
<el-menu-item
:index=
"item.path+'/'+child.path"
>
{{
child
.
name
}}
</el-menu-item>
</router-link>
</
template
>
</el-submenu>
</template>
</div>
</template>
<
script
>
export
default
{
name
:
'SidebarItem'
,
props
:
{
routes
:
{
type
:
Array
}
export
default
{
name
:
'SidebarItem'
,
props
:
{
routes
:
{
type
:
Array
}
}
}
</
script
>
<
style
rel=
"stylesheet/scss"
lang=
"scss"
scoped
>
.svg-icon
{
margin-right
:
10px
;
}
.hideSidebar
.menu-indent
{
display
:
block
;
text-indent
:
10px
;
}
.svg-icon
{
margin-right
:
10px
;
}
.hideSidebar
.menu-indent
{
display
:
block
;
text-indent
:
10px
;
}
</
style
>
src/views/layout/TabsView.vue
View file @
de992c50
...
...
@@ -5,48 +5,47 @@
{{
tag
.
name
}}
</el-tag>
</router-link>
</div>
</div>
</
template
>
<
script
>
export
default
{
computed
:
{
visitedViews
()
{
return
this
.
$store
.
state
.
app
.
visitedViews
.
slice
(
-
6
)
}
export
default
{
computed
:
{
visitedViews
()
{
return
this
.
$store
.
state
.
app
.
visitedViews
.
slice
(
-
6
)
}
},
methods
:
{
closeViewTabs
(
view
,
$event
)
{
this
.
$store
.
dispatch
(
'delVisitedViews'
,
view
)
$event
.
preventDefault
()
},
methods
:
{
closeViewTabs
(
view
,
$event
)
{
this
.
$store
.
dispatch
(
'delVisitedViews'
,
view
)
$event
.
preventDefault
()
},
generateRoute
()
{
if
(
this
.
$route
.
matched
[
this
.
$route
.
matched
.
length
-
1
].
name
)
{
return
this
.
$route
.
matched
[
this
.
$route
.
matched
.
length
-
1
]
}
this
.
$route
.
matched
[
0
].
path
=
'/'
return
this
.
$route
.
matched
[
0
]
},
addViewTabs
()
{
this
.
$store
.
dispatch
(
'addVisitedViews'
,
this
.
generateRoute
())
generateRoute
()
{
if
(
this
.
$route
.
matched
[
this
.
$route
.
matched
.
length
-
1
].
name
)
{
return
this
.
$route
.
matched
[
this
.
$route
.
matched
.
length
-
1
]
}
this
.
$route
.
matched
[
0
].
path
=
'/'
return
this
.
$route
.
matched
[
0
]
},
watch
:
{
$route
()
{
this
.
addViewTabs
()
}
addViewTabs
()
{
this
.
$store
.
dispatch
(
'addVisitedViews'
,
this
.
generateRoute
())
}
},
watch
:
{
$route
()
{
this
.
addViewTabs
()
}
}
}
</
script
>
<
style
rel=
"stylesheet/scss"
lang=
"scss"
scoped
>
.tabs-view-container
{
.tabs-view-container
{
display
:
inline-block
;
vertical-align
:
top
;
margin-left
:
10px
;
.tabs-view
{
.tabs-view
{
margin-left
:
10px
;
}
}
</
style
>
src/views/login/index.vue
View file @
de992c50
...
...
@@ -20,72 +20,74 @@
<div
class=
'tips'
>
admin账号为:admin@wallstreetcn.com 密码随便填
</div>
<div
class=
'tips'
>
editor账号:editor@wallstreetcn.com 密码随便填
</div>
</el-form>
<el-dialog
title=
"第三方验证"
:visible
.
sync=
"showDialog"
>
邮箱登录成功,请选择第三方验证
<social
Sign></socialS
ign>
<social
-sign></social-s
ign>
</el-dialog>
</div>
</
template
>
<
script
>
import
{
isWscnEmail
}
from
'utils/validate'
;
import
socialSign
from
'./socialsignin'
;
import
{
isWscnEmail
}
from
'utils/validate'
;
import
socialSign
from
'./socialsignin'
;
export
default
{
components
:
{
socialSign
},
name
:
'login'
,
data
()
{
const
validateEmail
=
(
rule
,
value
,
callback
)
=>
{
if
(
!
isWscnEmail
(
value
))
{
callback
(
new
Error
(
'请输入正确的合法邮箱'
));
}
else
{
callback
();
}
};
const
validatePass
=
(
rule
,
value
,
callback
)
=>
{
if
(
value
.
length
<
6
)
{
callback
(
new
Error
(
'密码不能小于6位'
));
}
else
{
callback
();
}
};
return
{
loginForm
:
{
email
:
'admin@wallstreetcn.com'
,
password
:
''
},
loginRules
:
{
email
:
[
export
default
{
components
:
{
socialSign
},
name
:
'login'
,
data
()
{
const
validateEmail
=
(
rule
,
value
,
callback
)
=>
{
if
(
!
isWscnEmail
(
value
))
{
callback
(
new
Error
(
'请输入正确的合法邮箱'
));
}
else
{
callback
();
}
};
const
validatePass
=
(
rule
,
value
,
callback
)
=>
{
if
(
value
.
length
<
6
)
{
callback
(
new
Error
(
'密码不能小于6位'
));
}
else
{
callback
();
}
};
return
{
loginForm
:
{
email
:
'admin@wallstreetcn.com'
,
password
:
''
},
loginRules
:
{
email
:
[
{
required
:
true
,
trigger
:
'blur'
,
validator
:
validateEmail
}
],
password
:
[
],
password
:
[
{
required
:
true
,
trigger
:
'blur'
,
validator
:
validatePass
}
]
},
loading
:
false
,
showDialog
:
false
}
},
methods
:
{
handleLogin
()
{
this
.
$refs
.
loginForm
.
validate
(
valid
=>
{
if
(
valid
)
{
this
.
loading
=
true
;
this
.
$store
.
dispatch
(
'LoginByEmail'
,
this
.
loginForm
).
then
(()
=>
{
this
.
loading
=
false
;
this
.
$router
.
push
({
path
:
'/'
});
// this.showDialog = true;
}).
catch
(
err
=>
{
this
.
$message
.
error
(
err
);
this
.
loading
=
false
;
});
}
else
{
console
.
log
(
'error submit!!'
);
return
false
;
}
});
]
},
afterQRScan
()
{
loading
:
false
,
showDialog
:
false
}
},
methods
:
{
handleLogin
()
{
this
.
$refs
.
loginForm
.
validate
(
valid
=>
{
if
(
valid
)
{
this
.
loading
=
true
;
this
.
$store
.
dispatch
(
'LoginByEmail'
,
this
.
loginForm
).
then
(()
=>
{
this
.
loading
=
false
;
this
.
$router
.
push
({
path
:
'/'
});
// this.showDialog = true;
}).
catch
(
err
=>
{
this
.
$message
.
error
(
err
);
this
.
loading
=
false
;
});
}
else
{
console
.
log
(
'error submit!!'
);
return
false
;
}
});
},
afterQRScan
()
{
// const hash = window.location.hash.slice(1);
// const hashObj = getQueryObject(hash);
// const originUrl = window.location.origin;
...
...
@@ -102,80 +104,75 @@
// this.$router.push({ path: '/' });
// });
// }
}
},
created
()
{
}
},
created
()
{
// window.addEventListener('hashchange', this.afterQRScan);
},
destroyed
()
{
},
destroyed
()
{
// window.removeEventListener('hashchange', this.afterQRScan);
}
}
}
</
script
>
<
style
rel=
"stylesheet/scss"
lang=
"scss"
>
@import
"src/styles/mixin.scss"
;
.tips
{
font-size
:
14px
;
color
:
#fff
;
margin-bottom
:
5px
;
}
.login-container
{
@include
relative
;
height
:
100vh
;
background-color
:
#2d3a4b
;
input
:
-
webkit-autofill
{
-webkit-box-shadow
:
0
0
0px
1000px
#293444
inset
!
important
;
-webkit-text-fill-color
:
#fff
!
important
;
}
input
{
background
:
transparent
;
border
:
0px
;
-webkit-appearance
:
none
;
border-radius
:
0px
;
padding
:
12px
5px
12px
15px
;
color
:
#eeeeee
;
height
:
47px
;
}
.el-input
{
display
:
inline-block
;
height
:
47px
;
width
:
85%
;
}
.svg-container
{
padding
:
6px
5px
6px
15px
;
color
:
#889aa4
;
}
.title
{
font-size
:
26px
;
font-weight
:
400
;
color
:
#eeeeee
;
margin
:
0px
auto
40px
auto
;
text-align
:
center
;
font-weight
:
bold
;
}
.login-form
{
position
:
absolute
;
left
:
0
;
right
:
0
;
width
:
400px
;
padding
:
35px
35px
15px
35px
;
margin
:
120px
auto
;
}
.el-form-item
{
border
:
1px
solid
rgba
(
255
,
255
,
255
,
0
.1
);
background
:
rgba
(
0
,
0
,
0
,
0
.1
);
border-radius
:
5px
;
color
:
#454545
;
}
@import
"src/styles/mixin.scss"
;
.tips
{
font-size
:
14px
;
color
:
#fff
;
margin-bottom
:
5px
;
}
.forget-pwd
{
color
:
#fff
;
}
.login-container
{
@include
relative
;
height
:
100vh
;
background-color
:
#2d3a4b
;
input
:
-
webkit-autofill
{
-webkit-box-shadow
:
0
0
0px
1000px
#293444
inset
!
important
;
-webkit-text-fill-color
:
#fff
!
important
;
}
input
{
background
:
transparent
;
border
:
0px
;
-webkit-appearance
:
none
;
border-radius
:
0px
;
padding
:
12px
5px
12px
15px
;
color
:
#eeeeee
;
height
:
47px
;
}
.el-input
{
display
:
inline-block
;
height
:
47px
;
width
:
85%
;
}
.svg-container
{
padding
:
6px
5px
6px
15px
;
color
:
#889aa4
;
}
.title
{
font-size
:
26px
;
font-weight
:
400
;
color
:
#eeeeee
;
margin
:
0px
auto
40px
auto
;
text-align
:
center
;
font-weight
:
bold
;
}
.login-form
{
position
:
absolute
;
left
:
0
;
right
:
0
;
width
:
400px
;
padding
:
35px
35px
15px
35px
;
margin
:
120px
auto
;
}
.el-form-item
{
border
:
1px
solid
rgba
(
255
,
255
,
255
,
0
.1
);
background
:
rgba
(
0
,
0
,
0
,
0
.1
);
border-radius
:
5px
;
color
:
#454545
;
}
.forget-pwd
{
color
:
#fff
;
}
}
</
style
>
src/views/login/socialsignin.vue
View file @
de992c50
<
template
>
<div
class=
"social-signup-container"
>
<div
class=
"sign-btn"
@
click=
"wechatHandleClick('wechat')"
>
<span
class=
"wx-svg-container"
><icon-svg
icon-class=
"weixin"
class=
"icon"
></icon-svg></span>
微信
</div>
<div
class=
"sign-btn"
@
click=
"tencentHandleClick('tencent')"
>
<span
class=
"qq-svg-container"
><icon-svg
icon-class=
"QQ"
class=
"icon"
></icon-svg></span>
QQ
</div>
</div>
<div
class=
"social-signup-container"
>
<div
class=
"sign-btn"
@
click=
"wechatHandleClick('wechat')"
>
<span
class=
"wx-svg-container"
><icon-svg
icon-class=
"weixin"
class=
"icon"
></icon-svg></span>
微信
</div>
<div
class=
"sign-btn"
@
click=
"tencentHandleClick('tencent')"
>
<span
class=
"qq-svg-container"
><icon-svg
icon-class=
"QQ"
class=
"icon"
></icon-svg></span>
QQ
</div>
</div>
</
template
>
<
script
>
import
openWindow
from
'utils/openWindow'
;
import
openWindow
from
'utils/openWindow'
;
export
default
{
name
:
'social-signin'
,
methods
:
{
wechatHandleClick
(
thirdpart
)
{
this
.
$store
.
commit
(
'SET_AUTH_TYPE'
,
thirdpart
);
const
appid
=
'xxxxx'
;
const
redirect_uri
=
encodeURIComponent
(
'xxx/redirect?redirect='
+
window
.
location
.
origin
+
'/authredirect'
);
const
url
=
'https://open.weixin.qq.com/connect/qrconnect?appid='
+
appid
+
'&redirect_uri='
+
redirect_uri
+
'&response_type=code&scope=snsapi_login#wechat_redirect'
;
openWindow
(
url
,
thirdpart
,
540
,
540
);
},
tencentHandleClick
(
thirdpart
)
{
this
.
$store
.
commit
(
'SET_AUTH_TYPE'
,
thirdpart
);
const
client_id
=
'xxxxx'
;
const
redirect_uri
=
encodeURIComponent
(
'xxx/redirect?redirect='
+
window
.
location
.
origin
+
'/authredirect'
);
const
url
=
'https://graph.qq.com/oauth2.0/authorize?response_type=code&client_id='
+
client_id
+
'&redirect_uri='
+
redirect_uri
;
openWindow
(
url
,
thirdpart
,
540
,
540
);
}
export
default
{
name
:
'social-signin'
,
methods
:
{
wechatHandleClick
(
thirdpart
)
{
this
.
$store
.
commit
(
'SET_AUTH_TYPE'
,
thirdpart
);
const
appid
=
'xxxxx'
;
const
redirect_uri
=
encodeURIComponent
(
'xxx/redirect?redirect='
+
window
.
location
.
origin
+
'/authredirect'
);
const
url
=
'https://open.weixin.qq.com/connect/qrconnect?appid='
+
appid
+
'&redirect_uri='
+
redirect_uri
+
'&response_type=code&scope=snsapi_login#wechat_redirect'
;
openWindow
(
url
,
thirdpart
,
540
,
540
);
},
tencentHandleClick
(
thirdpart
)
{
this
.
$store
.
commit
(
'SET_AUTH_TYPE'
,
thirdpart
);
const
client_id
=
'xxxxx'
;
const
redirect_uri
=
encodeURIComponent
(
'xxx/redirect?redirect='
+
window
.
location
.
origin
+
'/authredirect'
);
const
url
=
'https://graph.qq.com/oauth2.0/authorize?response_type=code&client_id='
+
client_id
+
'&redirect_uri='
+
redirect_uri
;
openWindow
(
url
,
thirdpart
,
540
,
540
);
}
}
}
</
script
>
<
style
rel=
"stylesheet/scss"
lang=
"scss"
scoped
>
.social-signup-container
{
margin
:
20px
0
;
.sign-btn
{
display
:
inline-block
;
cursor
:
pointer
;
}
.icon
{
color
:
#fff
;
font-size
:
30px
;
margin-top
:
6px
;
}
.wx-svg-container
,
.qq-svg-container
{
display
:
inline-block
;
width
:
40px
;
height
:
40px
;
line-height
:
40px
;
text-align
:
center
;
padding-top
:
1px
;
border-radius
:
4px
;
margin-bottom
:
20px
;
margin-right
:
5px
;
}
.wx-svg-container
{
background-color
:
#8dc349
;
}
.qq-svg-container
{
background-color
:
#6BA2D6
;
margin-left
:
50px
;
}
}
.social-signup-container
{
margin
:
20px
0
;
.sign-btn
{
display
:
inline-block
;
cursor
:
pointer
;
}
.icon
{
color
:
#fff
;
font-size
:
30px
;
margin-top
:
6px
;
}
.wx-svg-container
,
.qq-svg-container
{
display
:
inline-block
;
width
:
40px
;
height
:
40px
;
line-height
:
40px
;
text-align
:
center
;
padding-top
:
1px
;
border-radius
:
4px
;
margin-bottom
:
20px
;
margin-right
:
5px
;
}
.wx-svg-container
{
background-color
:
#8dc349
;
}
.qq-svg-container
{
background-color
:
#6BA2D6
;
margin-left
:
50px
;
}
}
</
style
>
src/views/permission/index.vue
View file @
de992c50
...
...
@@ -9,24 +9,24 @@
</
template
>
<
script
>
import
{
mapGetters
}
from
'vuex'
;
export
default
{
data
()
{
return
{
role
:
''
}
},
computed
:
{
...
mapGetters
([
'roles'
])
},
watch
:
{
role
(
val
)
{
this
.
$store
.
dispatch
(
'ChangeRole'
,
val
).
then
(()
=>
{
this
.
$router
.
push
({
path
:
'/permission/index?'
+
+
new
Date
()
});
})
}
import
{
mapGetters
}
from
'vuex'
;
export
default
{
data
()
{
return
{
role
:
''
}
},
computed
:
{
...
mapGetters
([
'roles'
])
},
watch
:
{
role
(
val
)
{
this
.
$store
.
dispatch
(
'ChangeRole'
,
val
).
then
(()
=>
{
this
.
$router
.
push
({
path
:
'/permission/index?'
+
+
new
Date
()
});
})
}
}
}
</
script
>
src/views/qiniu/upload.vue
View file @
de992c50
<
template
>
<el-upload
action=
"https://upload.qbox.me"
:data=
"dataObj"
drag
:multiple=
"true"
:before-upload=
"beforeUpload"
>
<el-upload
action=
"https://upload.qbox.me"
:data=
"dataObj"
drag
:multiple=
"true"
:before-upload=
"beforeUpload"
>
<i
class=
"el-icon-upload"
></i>
<div
class=
"el-upload__text"
>
将文件拖到此处,或
<em>
点击上传
</em></div>
</el-upload>
...
...
@@ -12,33 +7,33 @@
<
script
>
import
{
getToken
}
from
'api/qiniu'
;
// 获取七牛token 后端通过Access Key,Secret Key,bucket等生成token
import
{
getToken
}
from
'api/qiniu'
;
// 获取七牛token 后端通过Access Key,Secret Key,bucket等生成token
// 七牛官方sdk https://developer.qiniu.com/sdk#official-sdk
export
default
{
data
()
{
return
{
dataObj
:
{
token
:
''
,
key
:
''
},
image_uri
:
[],
fileList
:
[]
}
},
methods
:
{
beforeUpload
()
{
const
_self
=
this
;
return
new
Promise
((
resolve
,
reject
)
=>
{
getToken
().
then
(
response
=>
{
const
key
=
response
.
data
.
qiniu_key
;
const
token
=
response
.
data
.
qiniu_token
;
_self
.
_data
.
dataObj
.
token
=
token
;
_self
.
_data
.
dataObj
.
key
=
key
;
resolve
(
true
);
}).
catch
(
err
=>
{
console
.
log
(
err
)
reject
(
false
)
});
export
default
{
data
()
{
return
{
dataObj
:
{
token
:
''
,
key
:
''
},
image_uri
:
[],
fileList
:
[]
}
},
methods
:
{
beforeUpload
()
{
const
_self
=
this
;
return
new
Promise
((
resolve
,
reject
)
=>
{
getToken
().
then
(
response
=>
{
const
key
=
response
.
data
.
qiniu_key
;
const
token
=
response
.
data
.
qiniu_token
;
_self
.
_data
.
dataObj
.
token
=
token
;
_self
.
_data
.
dataObj
.
key
=
key
;
resolve
(
true
);
}).
catch
(
err
=>
{
console
.
log
(
err
)
reject
(
false
)
});
}
}
);
}
}
}
</
script
>
src/views/theme/index.vue
View file @
de992c50
...
...
@@ -45,31 +45,48 @@
<
script
>
import
{
toggleClass
}
from
'utils'
;
import
{
toggleClass
}
from
'utils'
;
export
default
{
data
()
{
return
{
theme
:
false
,
tags
:
[
{
name
:
'标签一'
,
type
:
''
},
{
name
:
'标签二'
,
type
:
'gray'
},
{
name
:
'标签三'
,
type
:
'primary'
},
{
name
:
'标签四'
,
type
:
'success'
},
{
name
:
'标签五'
,
type
:
'warning'
},
{
name
:
'标签六'
,
type
:
'danger'
}
],
inputVisible
:
false
,
inputValue
:
''
}
},
watch
:
{
theme
()
{
toggleClass
(
document
.
body
,
'custom-theme'
)
export
default
{
data
()
{
return
{
theme
:
false
,
tags
:
[{
name
:
'标签一'
,
type
:
''
},
{
name
:
'标签二'
,
type
:
'gray'
},
{
name
:
'标签三'
,
type
:
'primary'
},
{
name
:
'标签四'
,
type
:
'success'
},
{
name
:
'标签五'
,
type
:
'warning'
},
{
name
:
'标签六'
,
type
:
'danger'
}
],
inputVisible
:
false
,
inputValue
:
''
}
},
watch
:
{
theme
()
{
toggleClass
(
document
.
body
,
'custom-theme'
)
// this.$store.dispatch('setTheme', value);
}
}
}
};
};
</
script
>
<
style
scoped
>
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment