no message
Former-commit-id: 0a96bb54e9270e451e59b72e00e35053a7c0e152 Former-commit-id: c250ba90da6546626b9831847630aae786c88344 Former-commit-id: c1182b1bdc6ea9b3934275286a93e2760a643bfe
This commit is contained in:
27
src/components/core/Container/index.vue
Normal file
27
src/components/core/Container/index.vue
Normal file
@@ -0,0 +1,27 @@
|
||||
<template>
|
||||
<div class="container-component">
|
||||
<!-- [card] 卡片容器 -->
|
||||
<el-card v-if="type === 'card'">
|
||||
<div v-if="$slots.header" slot="header">
|
||||
<slot name="header"></slot>
|
||||
</div>
|
||||
<slot></slot>
|
||||
</el-card>
|
||||
<!-- [ghost] 隐形的容器 -->
|
||||
<div v-if="type === 'ghost'">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
type: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: 'card'
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
102
src/components/core/CountUp/index.vue
Normal file
102
src/components/core/CountUp/index.vue
Normal file
@@ -0,0 +1,102 @@
|
||||
<template>
|
||||
<span></span>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import CountUp from 'countup.js'
|
||||
export default {
|
||||
props: {
|
||||
start: {
|
||||
type: Number,
|
||||
required: false,
|
||||
default: 0
|
||||
},
|
||||
end: {
|
||||
type: Number,
|
||||
required: true
|
||||
},
|
||||
decimals: {
|
||||
type: Number,
|
||||
required: false,
|
||||
default: 0
|
||||
},
|
||||
duration: {
|
||||
type: Number,
|
||||
required: false,
|
||||
default: 2
|
||||
},
|
||||
options: {
|
||||
type: Object,
|
||||
required: false,
|
||||
default () {
|
||||
return {}
|
||||
}
|
||||
},
|
||||
callback: {
|
||||
type: Function,
|
||||
required: false,
|
||||
default: () => {}
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
c: null
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
end (value) {
|
||||
if (this.c && this.c.update) {
|
||||
this.c.update(value)
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.init()
|
||||
},
|
||||
methods: {
|
||||
init () {
|
||||
if (!this.c) {
|
||||
this.c = new CountUp(
|
||||
this.$el,
|
||||
this.start,
|
||||
this.end,
|
||||
this.decimals,
|
||||
this.duration,
|
||||
this.options
|
||||
)
|
||||
this.c.start(() => {
|
||||
this.callback(this.c)
|
||||
})
|
||||
}
|
||||
},
|
||||
destroy () {
|
||||
this.c = null
|
||||
}
|
||||
},
|
||||
beforeDestroy () {
|
||||
this.destroy()
|
||||
},
|
||||
start (callback) {
|
||||
if (this.c && this.c.start) {
|
||||
this.c.start(() => {
|
||||
callback && callback(this.c)
|
||||
})
|
||||
}
|
||||
},
|
||||
pauseResume () {
|
||||
if (this.c && this.c.pauseResume) {
|
||||
this.c.pauseResume()
|
||||
}
|
||||
},
|
||||
reset () {
|
||||
if (this.c && this.c.reset) {
|
||||
this.c.reset()
|
||||
}
|
||||
},
|
||||
update (newEndVal) {
|
||||
if (this.c && this.c.update) {
|
||||
this.c.update(newEndVal)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
36
src/components/core/Highlight/index.vue
Normal file
36
src/components/core/Highlight/index.vue
Normal file
@@ -0,0 +1,36 @@
|
||||
<template>
|
||||
<pre v-html="highlightHTML"></pre>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// https://highlightjs.org/usage/
|
||||
// http://highlightjs.readthedocs.io/en/latest/api.html#configure-options
|
||||
import highlight from 'highlight.js'
|
||||
export default {
|
||||
props: {
|
||||
code: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: `console.log('Hello')`
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
highlightHTML: ''
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.highlight()
|
||||
},
|
||||
watch: {
|
||||
code () {
|
||||
this.highlight()
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
highlight () {
|
||||
this.highlightHTML = highlight.highlightAuto(this.code).value
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
88
src/components/core/MainLayout/_headerMenu.vue
Normal file
88
src/components/core/MainLayout/_headerMenu.vue
Normal file
@@ -0,0 +1,88 @@
|
||||
<template>
|
||||
<el-menu class="el-menu-demo" mode="horizontal">
|
||||
<el-menu-item index="index" @click.native="active({name: 'index'})">首页</el-menu-item>
|
||||
<el-menu-item
|
||||
v-for="(item, index) in menu"
|
||||
:key="index"
|
||||
:index="String(index)"
|
||||
@click.native="active(item)">
|
||||
{{item.title}}
|
||||
</el-menu-item>
|
||||
</el-menu>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapMutations } from 'vuex'
|
||||
import { menu, router } from '@/router/menu/index.js'
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
menu,
|
||||
router
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
// 当前路由的name
|
||||
routeName () {
|
||||
return this.$route.name
|
||||
},
|
||||
// 当前路由是否是顶级菜单
|
||||
// 顶级菜单就是在顶栏里显示的菜单
|
||||
// 二级菜单是在侧边栏显示的菜单
|
||||
// 三级菜单是二级菜单展开的
|
||||
routeIsTopLevel () {
|
||||
return !!this.router.find(e => e.name === this.routeName)
|
||||
},
|
||||
// 不管当前路由是不是顶级菜单 都返回这个路由所属的顶级菜单对象的name
|
||||
// 如果返回 undefined 代表这个路由不是在菜单里显示的路由
|
||||
routeTopLevel () {
|
||||
if (this.routeIsTopLevel) {
|
||||
return this.routeName
|
||||
} else {
|
||||
const find = this.router.find(e => {
|
||||
return e.children.find(child => {
|
||||
return child.name === this.routeName
|
||||
})
|
||||
})
|
||||
return find ? find.name : undefined
|
||||
}
|
||||
},
|
||||
// 返回当前对象对应的顶级菜单 这个菜单可以在侧边栏菜单中直接使用
|
||||
// 如果返回 undefined 代表这个路由没有对应的一级路由也就没有菜单
|
||||
routeTopLevelMenu () {
|
||||
if (this.routeTopLevel) {
|
||||
return this.menu.find(e => e.name === this.routeTopLevel).children
|
||||
} else {
|
||||
return undefined
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
routeName () {
|
||||
this.doSetSideMenu()
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.doSetSideMenu()
|
||||
},
|
||||
methods: {
|
||||
...mapMutations([
|
||||
'setSideMenu'
|
||||
]),
|
||||
// 更新一次侧边栏
|
||||
doSetSideMenu () {
|
||||
if (this.routeTopLevelMenu) {
|
||||
this.setSideMenu({
|
||||
sideMenu: this.routeTopLevelMenu
|
||||
})
|
||||
}
|
||||
},
|
||||
// 跳转到某个路由
|
||||
active (item) {
|
||||
this.$router.push({
|
||||
name: item.name
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
50
src/components/core/MainLayout/_siderMenu.vue
Normal file
50
src/components/core/MainLayout/_siderMenu.vue
Normal file
@@ -0,0 +1,50 @@
|
||||
<template>
|
||||
<el-menu class="el-menu-vertical-demo" v-bind="elMenu">
|
||||
<el-submenu
|
||||
v-for="(menu, index) in sideMenu"
|
||||
:key="index"
|
||||
:index="`${menu.title}${index}`">
|
||||
<template slot="title">
|
||||
<i v-if="menu.icon" :class="'fa fa-' + menu.icon"></i>
|
||||
<span slot="title">{{menu.title}}</span>
|
||||
</template>
|
||||
<el-menu-item
|
||||
v-for="(menuItem, menuItemIndex) in menu.children"
|
||||
:key="menuItemIndex"
|
||||
:index="`${menuItem.name}${menuItemIndex}`"
|
||||
@click.native="$router.push({name: menuItem.name})">
|
||||
<i v-if="menu.icon" :class="'fa fa-' + menuItem.icon"></i>
|
||||
{{menuItem.title}}
|
||||
</el-menu-item>
|
||||
</el-submenu>
|
||||
</el-menu>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapState } from 'vuex'
|
||||
import { menu, router } from '@/router/menu/index.js'
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
menu,
|
||||
router,
|
||||
elMenu: {
|
||||
collapse: false,
|
||||
uniqueOpened: true
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState({
|
||||
sideMenu: state => state.menu.sideMenu
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.el-menu-vertical-demo:not(.el-menu--collapse) {
|
||||
width: 200px;
|
||||
min-height: 400px;
|
||||
}
|
||||
</style>
|
||||
37
src/components/core/MainLayout/index.vue
Normal file
37
src/components/core/MainLayout/index.vue
Normal file
@@ -0,0 +1,37 @@
|
||||
<template>
|
||||
<el-container class="layout-main" :class="theme">
|
||||
<el-header>
|
||||
<HeaderMenu></HeaderMenu>
|
||||
</el-header>
|
||||
<el-container>
|
||||
<el-aside style="width: 200px;">
|
||||
<SiderMenu></SiderMenu>
|
||||
</el-aside>
|
||||
<el-main>
|
||||
<router-view></router-view>
|
||||
</el-main>
|
||||
</el-container>
|
||||
</el-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import SiderMenu from '@/components/core/MainLayout/_siderMenu.vue'
|
||||
import HeaderMenu from '@/components/core/MainLayout/_headerMenu.vue'
|
||||
export default {
|
||||
components: {
|
||||
SiderMenu,
|
||||
HeaderMenu
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
theme: 'default'
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
// 主题
|
||||
@import '~@/assets/style/theme/default.scss';
|
||||
</style>
|
||||
|
||||
78
src/components/core/Markdown/index.vue
Normal file
78
src/components/core/Markdown/index.vue
Normal file
@@ -0,0 +1,78 @@
|
||||
<template>
|
||||
<div class="component-markdown">
|
||||
<div class="spin-group" v-if="!markedHTML">
|
||||
<div>正在加载</div>
|
||||
</div>
|
||||
<div class="markdown-body" v-html="markedHTML"></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import marked from 'marked'
|
||||
import highlight from 'highlight.js'
|
||||
export default {
|
||||
props: {
|
||||
url: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: ''
|
||||
},
|
||||
md: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
getReadmePublicPath: '',
|
||||
markedHTML: ''
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
if (this.url) {
|
||||
this.initWithUrl()
|
||||
} else if (this.md) {
|
||||
this.initWithMd()
|
||||
} else {
|
||||
console.log('not mounted init')
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 使用 md 初始化
|
||||
initWithMd () {
|
||||
this.markedHTML = this.marked(this.md)
|
||||
console.log(this.markedHTML)
|
||||
},
|
||||
// 使用 url 初始化
|
||||
async initWithUrl () {
|
||||
this.markedHTML = await this.getReadme(this.url)
|
||||
},
|
||||
// 从 url 加载原始数据
|
||||
async getReadme (name) {
|
||||
const { data } = await this.$axios.get(name)
|
||||
return this.marked(data)
|
||||
},
|
||||
marked (data) {
|
||||
return marked(data, {
|
||||
highlight: (code) => highlight.highlightAuto(code).value
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import '~@/assets/style/public.scss';
|
||||
.component-markdown {
|
||||
.spin-group {
|
||||
height: 100px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
color: $color-primary;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
110
src/components/core/SimpleMDE/backup.vue
Normal file
110
src/components/core/SimpleMDE/backup.vue
Normal file
@@ -0,0 +1,110 @@
|
||||
<template>
|
||||
<div class="markdown-editor">
|
||||
<textarea></textarea>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import SimpleMDE from 'simplemde'
|
||||
import marked from 'marked'
|
||||
|
||||
export default {
|
||||
name: 'markdown-editor',
|
||||
props: {
|
||||
value: String,
|
||||
previewClass: String,
|
||||
autoinit: {
|
||||
type: Boolean,
|
||||
default () {
|
||||
return true
|
||||
}
|
||||
},
|
||||
highlight: {
|
||||
type: Boolean,
|
||||
default () {
|
||||
return false
|
||||
}
|
||||
},
|
||||
sanitize: {
|
||||
type: Boolean,
|
||||
default () {
|
||||
return false
|
||||
}
|
||||
},
|
||||
configs: {
|
||||
type: Object,
|
||||
default () {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
if (this.autoinit) this.initialize()
|
||||
},
|
||||
activated () {
|
||||
const editor = this.simplemde
|
||||
if (!editor) return
|
||||
const isActive = editor.isSideBySideActive() || editor.isPreviewActive()
|
||||
if (isActive) editor.toggleFullScreen()
|
||||
},
|
||||
methods: {
|
||||
initialize () {
|
||||
const configs = {
|
||||
element: this.$el.firstElementChild,
|
||||
initialValue: this.value,
|
||||
renderingConfig: {}
|
||||
}
|
||||
Object.assign(configs, this.configs)
|
||||
|
||||
// 判断是否开启代码高亮
|
||||
if (this.highlight) {
|
||||
configs.renderingConfig.codeSyntaxHighlighting = true
|
||||
}
|
||||
|
||||
// 设置是否渲染输入的html
|
||||
marked.setOptions({ sanitize: this.sanitize })
|
||||
|
||||
// 实例化编辑器
|
||||
this.simplemde = new SimpleMDE(configs)
|
||||
|
||||
// 添加自定义 previewClass
|
||||
const className = this.previewClass || ''
|
||||
this.addPreviewClass(className)
|
||||
|
||||
// 绑定事件
|
||||
this.bindingEvents()
|
||||
},
|
||||
bindingEvents () {
|
||||
this.simplemde.codemirror.on('change', () => {
|
||||
this.$emit('input', this.simplemde.value())
|
||||
})
|
||||
},
|
||||
addPreviewClass (className) {
|
||||
const wrapper = this.simplemde.codemirror.getWrapperElement()
|
||||
const preview = document.createElement('div')
|
||||
wrapper.nextSibling.className += ` ${className}`
|
||||
preview.className = `editor-preview ${className}`
|
||||
wrapper.appendChild(preview)
|
||||
}
|
||||
},
|
||||
destroyed () {
|
||||
this.simplemde = null
|
||||
},
|
||||
watch: {
|
||||
value (val) {
|
||||
if (val === this.simplemde.value()) return
|
||||
this.simplemde.value(val)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.markdown-editor .markdown-body {
|
||||
padding: 0.5em
|
||||
}
|
||||
|
||||
.markdown-editor .editor-preview-active, .markdown-editor .editor-preview-active-side {
|
||||
display: block
|
||||
}
|
||||
</style>
|
||||
45
src/components/core/SimpleMDE/index.vue
Normal file
45
src/components/core/SimpleMDE/index.vue
Normal file
@@ -0,0 +1,45 @@
|
||||
<template>
|
||||
<div class="markdown-editor">
|
||||
<textarea ref="mde"></textarea>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import SimpleMDE from 'simplemde'
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
mde: null
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.init()
|
||||
},
|
||||
destroyed () {
|
||||
this.mde = null
|
||||
},
|
||||
methods: {
|
||||
init () {
|
||||
this.mde = new SimpleMDE({
|
||||
element: this.$refs.mde
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.markdown-editor {
|
||||
.markdown-body {
|
||||
padding: 0.5em;
|
||||
}
|
||||
}
|
||||
.markdown-editor {
|
||||
.editor-preview-active {
|
||||
display: block;
|
||||
}
|
||||
.editor-preview-active-side {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user