21 changed files with 1361 additions and 31 deletions
@ -0,0 +1,193 @@ |
|||||
|
<template> |
||||
|
<span> |
||||
|
{{ displayValue }} |
||||
|
</span> |
||||
|
</template> |
||||
|
<script> |
||||
|
import {requestAnimationFrame, cancelAnimationFrame} from './requestAnimationFrame.js' |
||||
|
|
||||
|
export default { |
||||
|
name: 'CountTo', |
||||
|
props: { |
||||
|
startVal: { |
||||
|
type: Number, |
||||
|
required: false, |
||||
|
default: 0 |
||||
|
}, |
||||
|
endVal: { |
||||
|
type: Number, |
||||
|
required: false, |
||||
|
default: 2017 |
||||
|
}, |
||||
|
duration: { |
||||
|
type: Number, |
||||
|
required: false, |
||||
|
default: 3000 |
||||
|
}, |
||||
|
autoplay: { |
||||
|
type: Boolean, |
||||
|
required: false, |
||||
|
default: true |
||||
|
}, |
||||
|
decimals: { |
||||
|
type: Number, |
||||
|
required: false, |
||||
|
default: 0, |
||||
|
validator(value) { |
||||
|
return value >= 0 |
||||
|
} |
||||
|
}, |
||||
|
decimal: { |
||||
|
type: String, |
||||
|
required: false, |
||||
|
default: '.' |
||||
|
}, |
||||
|
separator: { |
||||
|
type: String, |
||||
|
required: false, |
||||
|
default: ',' |
||||
|
}, |
||||
|
prefix: { |
||||
|
type: String, |
||||
|
required: false, |
||||
|
default: '' |
||||
|
}, |
||||
|
suffix: { |
||||
|
type: String, |
||||
|
required: false, |
||||
|
default: '' |
||||
|
}, |
||||
|
useEasing: { |
||||
|
type: Boolean, |
||||
|
required: false, |
||||
|
default: true |
||||
|
}, |
||||
|
easingFn: { |
||||
|
type: Function, |
||||
|
default(t, b, c, d) { |
||||
|
return c * (-Math.pow(2, -10 * t / d) + 1) * 1024 / 1023 + b |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
data() { |
||||
|
return { |
||||
|
localStartVal: this.startVal, |
||||
|
displayValue: this.formatNumber(this.startVal), |
||||
|
printVal: null, |
||||
|
paused: false, |
||||
|
localDuration: this.duration, |
||||
|
startTime: null, |
||||
|
timestamp: null, |
||||
|
remaining: null, |
||||
|
rAF: null |
||||
|
} |
||||
|
}, |
||||
|
computed: { |
||||
|
countDown() { |
||||
|
return this.startVal > this.endVal |
||||
|
} |
||||
|
}, |
||||
|
watch: { |
||||
|
startVal() { |
||||
|
if (this.autoplay) { |
||||
|
this.start() |
||||
|
} |
||||
|
}, |
||||
|
endVal() { |
||||
|
if (this.autoplay) { |
||||
|
this.start() |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
mounted() { |
||||
|
if (this.autoplay) { |
||||
|
this.start() |
||||
|
} |
||||
|
this.$emit('mountedCallback') |
||||
|
}, |
||||
|
methods: { |
||||
|
start() { |
||||
|
this.localStartVal = this.startVal |
||||
|
this.startTime = null |
||||
|
this.localDuration = this.duration |
||||
|
this.paused = false |
||||
|
this.rAF = requestAnimationFrame(this.count) |
||||
|
}, |
||||
|
pauseResume() { |
||||
|
if (this.paused) { |
||||
|
this.resume() |
||||
|
this.paused = false |
||||
|
} else { |
||||
|
this.pause() |
||||
|
this.paused = true |
||||
|
} |
||||
|
}, |
||||
|
pause() { |
||||
|
cancelAnimationFrame(this.rAF) |
||||
|
}, |
||||
|
resume() { |
||||
|
this.startTime = null |
||||
|
this.localDuration = +this.remaining |
||||
|
this.localStartVal = +this.printVal |
||||
|
requestAnimationFrame(this.count) |
||||
|
}, |
||||
|
reset() { |
||||
|
this.startTime = null |
||||
|
cancelAnimationFrame(this.rAF) |
||||
|
this.displayValue = this.formatNumber(this.startVal) |
||||
|
}, |
||||
|
count(timestamp) { |
||||
|
if (!this.startTime) this.startTime = timestamp |
||||
|
this.timestamp = timestamp |
||||
|
const progress = timestamp - this.startTime |
||||
|
this.remaining = this.localDuration - progress |
||||
|
|
||||
|
if (this.useEasing) { |
||||
|
if (this.countDown) { |
||||
|
this.printVal = this.localStartVal - this.easingFn(progress, 0, this.localStartVal - this.endVal, this.localDuration) |
||||
|
} else { |
||||
|
this.printVal = this.easingFn(progress, this.localStartVal, this.endVal - this.localStartVal, this.localDuration) |
||||
|
} |
||||
|
} else { |
||||
|
if (this.countDown) { |
||||
|
this.printVal = this.localStartVal - ((this.localStartVal - this.endVal) * (progress / this.localDuration)) |
||||
|
} else { |
||||
|
this.printVal = this.localStartVal + (this.endVal - this.localStartVal) * (progress / this.localDuration) |
||||
|
} |
||||
|
} |
||||
|
if (this.countDown) { |
||||
|
this.printVal = this.printVal < this.endVal ? this.endVal : this.printVal |
||||
|
} else { |
||||
|
this.printVal = this.printVal > this.endVal ? this.endVal : this.printVal |
||||
|
} |
||||
|
|
||||
|
this.displayValue = this.formatNumber(this.printVal) |
||||
|
if (progress < this.localDuration) { |
||||
|
this.rAF = requestAnimationFrame(this.count) |
||||
|
} else { |
||||
|
this.$emit('callback') |
||||
|
} |
||||
|
}, |
||||
|
isNumber(val) { |
||||
|
return !isNaN(parseFloat(val)) |
||||
|
}, |
||||
|
formatNumber(num) { |
||||
|
num = num.toFixed(this.decimals) |
||||
|
num += '' |
||||
|
const x = num.split('.') |
||||
|
let x1 = x[0] |
||||
|
const x2 = x.length > 1 ? this.decimal + x[1] : '' |
||||
|
const rgx = /(\d+)(\d{3})/ |
||||
|
if (this.separator && !this.isNumber(this.separator)) { |
||||
|
while (rgx.test(x1)) { |
||||
|
x1 = x1.replace(rgx, '$1' + this.separator + '$2') |
||||
|
} |
||||
|
} |
||||
|
return this.prefix + x1 + x2 + this.suffix |
||||
|
} |
||||
|
}, |
||||
|
destroyed() { |
||||
|
cancelAnimationFrame(this.rAF) |
||||
|
} |
||||
|
} |
||||
|
</script> |
@ -0,0 +1,46 @@ |
|||||
|
let lastTime = 0 |
||||
|
const prefixes = 'webkit moz ms o'.split(' ') // 各浏览器前缀
|
||||
|
|
||||
|
let requestAnimationFrame |
||||
|
let cancelAnimationFrame |
||||
|
|
||||
|
const isServer = typeof window === 'undefined' |
||||
|
if (isServer) { |
||||
|
requestAnimationFrame = function() { |
||||
|
return |
||||
|
} |
||||
|
cancelAnimationFrame = function() { |
||||
|
return |
||||
|
} |
||||
|
} else { |
||||
|
requestAnimationFrame = window.requestAnimationFrame |
||||
|
cancelAnimationFrame = window.cancelAnimationFrame |
||||
|
let prefix |
||||
|
// 通过遍历各浏览器前缀,来得到requestAnimationFrame和cancelAnimationFrame在当前浏览器的实现形式
|
||||
|
for (let i = 0; i < prefixes.length; i++) { |
||||
|
if (requestAnimationFrame && cancelAnimationFrame) { break } |
||||
|
prefix = prefixes[i] |
||||
|
requestAnimationFrame = requestAnimationFrame || window[prefix + 'RequestAnimationFrame'] |
||||
|
cancelAnimationFrame = cancelAnimationFrame || window[prefix + 'CancelAnimationFrame'] || window[prefix + 'CancelRequestAnimationFrame'] |
||||
|
} |
||||
|
|
||||
|
// 如果当前浏览器不支持requestAnimationFrame和cancelAnimationFrame,则会退到setTimeout
|
||||
|
if (!requestAnimationFrame || !cancelAnimationFrame) { |
||||
|
requestAnimationFrame = function(callback) { |
||||
|
const currTime = new Date().getTime() |
||||
|
// 为了使setTimteout的尽可能的接近每秒60帧的效果
|
||||
|
const timeToCall = Math.max(0, 16 - (currTime - lastTime)) |
||||
|
const id = window.setTimeout(() => { |
||||
|
callback(currTime + timeToCall) |
||||
|
}, timeToCall) |
||||
|
lastTime = currTime + timeToCall |
||||
|
return id |
||||
|
} |
||||
|
|
||||
|
cancelAnimationFrame = function(id) { |
||||
|
window.clearTimeout(id) |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
export { requestAnimationFrame, cancelAnimationFrame } |
@ -0,0 +1,102 @@ |
|||||
|
<template> |
||||
|
<div :class="className" :style="{height:height,width:width}" /> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
const echarts = require('echarts') |
||||
|
require('echarts/theme/macarons') // echarts theme |
||||
|
import resize from './mixins/resize' |
||||
|
|
||||
|
const animationDuration = 6000 |
||||
|
|
||||
|
export default { |
||||
|
mixins: [resize], |
||||
|
props: { |
||||
|
className: { |
||||
|
type: String, |
||||
|
default: 'chart' |
||||
|
}, |
||||
|
width: { |
||||
|
type: String, |
||||
|
default: '100%' |
||||
|
}, |
||||
|
height: { |
||||
|
type: String, |
||||
|
default: '300px' |
||||
|
} |
||||
|
}, |
||||
|
data() { |
||||
|
return { |
||||
|
chart: null |
||||
|
} |
||||
|
}, |
||||
|
mounted() { |
||||
|
this.$nextTick(() => { |
||||
|
this.initChart() |
||||
|
}) |
||||
|
}, |
||||
|
beforeDestroy() { |
||||
|
if (!this.chart) { |
||||
|
return |
||||
|
} |
||||
|
this.chart.dispose() |
||||
|
this.chart = null |
||||
|
}, |
||||
|
methods: { |
||||
|
initChart() { |
||||
|
this.chart = echarts.init(this.$el, 'macarons') |
||||
|
|
||||
|
this.chart.setOption({ |
||||
|
tooltip: { |
||||
|
trigger: 'axis', |
||||
|
axisPointer: { // 坐标轴指示器,坐标轴触发有效 |
||||
|
type: 'shadow' // 默认为直线,可选为:'line' | 'shadow' |
||||
|
} |
||||
|
}, |
||||
|
grid: { |
||||
|
top: 10, |
||||
|
left: '2%', |
||||
|
right: '2%', |
||||
|
bottom: '3%', |
||||
|
containLabel: true |
||||
|
}, |
||||
|
xAxis: [{ |
||||
|
type: 'category', |
||||
|
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'], |
||||
|
axisTick: { |
||||
|
alignWithLabel: true |
||||
|
} |
||||
|
}], |
||||
|
yAxis: [{ |
||||
|
type: 'value', |
||||
|
axisTick: { |
||||
|
show: false |
||||
|
} |
||||
|
}], |
||||
|
series: [{ |
||||
|
name: 'pageA', |
||||
|
type: 'bar', |
||||
|
stack: 'vistors', |
||||
|
barWidth: '60%', |
||||
|
data: [79, 52, 200, 334, 390, 330, 220], |
||||
|
animationDuration |
||||
|
}, { |
||||
|
name: 'pageB', |
||||
|
type: 'bar', |
||||
|
stack: 'vistors', |
||||
|
barWidth: '60%', |
||||
|
data: [80, 52, 200, 334, 390, 330, 220], |
||||
|
animationDuration |
||||
|
}, { |
||||
|
name: 'pageC', |
||||
|
type: 'bar', |
||||
|
stack: 'vistors', |
||||
|
barWidth: '60%', |
||||
|
data: [30, 52, 200, 334, 390, 330, 220], |
||||
|
animationDuration |
||||
|
}] |
||||
|
}) |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
</script> |
@ -0,0 +1,118 @@ |
|||||
|
<template> |
||||
|
<el-card class="box-card-component" style="margin-left:8px;"> |
||||
|
<div slot="header" class="box-card-header"> |
||||
|
<img src="https://wpimg.wallstcn.com/e7d23d71-cf19-4b90-a1cc-f56af8c0903d.png"> |
||||
|
</div> |
||||
|
<div style="position:relative;"> |
||||
|
<pan-thumb :image="avatar" class="panThumb" /> |
||||
|
<mallki class-name="mallki-text" text="vue-element-admin" /> |
||||
|
<div style="padding-top:35px;" class="progress-item"> |
||||
|
<span>Vue</span> |
||||
|
<el-progress :percentage="70" /> |
||||
|
</div> |
||||
|
<div class="progress-item"> |
||||
|
<span>JavaScript</span> |
||||
|
<el-progress :percentage="18" /> |
||||
|
</div> |
||||
|
<div class="progress-item"> |
||||
|
<span>CSS</span> |
||||
|
<el-progress :percentage="12" /> |
||||
|
</div> |
||||
|
<div class="progress-item"> |
||||
|
<span>ESLint</span> |
||||
|
<el-progress :percentage="100" status="success" /> |
||||
|
</div> |
||||
|
</div> |
||||
|
</el-card> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
import { mapGetters } from 'vuex' |
||||
|
import PanThumb from '@/components/PanThumb' |
||||
|
import Mallki from '@/components/TextHoverEffect/Mallki' |
||||
|
|
||||
|
export default { |
||||
|
components: { PanThumb, Mallki }, |
||||
|
|
||||
|
filters: { |
||||
|
statusFilter(status) { |
||||
|
const statusMap = { |
||||
|
success: 'success', |
||||
|
pending: 'danger' |
||||
|
} |
||||
|
return statusMap[status] |
||||
|
} |
||||
|
}, |
||||
|
data() { |
||||
|
return { |
||||
|
statisticsData: { |
||||
|
article_count: 1024, |
||||
|
pageviews_count: 1024 |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
computed: { |
||||
|
...mapGetters([ |
||||
|
'name', |
||||
|
'avatar', |
||||
|
'roles' |
||||
|
]) |
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<style lang="scss" > |
||||
|
.box-card-component{ |
||||
|
.el-card__header { |
||||
|
padding: 0px!important; |
||||
|
} |
||||
|
} |
||||
|
</style> |
||||
|
<style lang="scss" scoped> |
||||
|
.box-card-component { |
||||
|
.box-card-header { |
||||
|
position: relative; |
||||
|
height: 220px; |
||||
|
img { |
||||
|
width: 100%; |
||||
|
height: 100%; |
||||
|
transition: all 0.2s linear; |
||||
|
&:hover { |
||||
|
transform: scale(1.1, 1.1); |
||||
|
filter: contrast(130%); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
.mallki-text { |
||||
|
position: absolute; |
||||
|
top: 0px; |
||||
|
right: 0px; |
||||
|
font-size: 20px; |
||||
|
font-weight: bold; |
||||
|
} |
||||
|
.panThumb { |
||||
|
z-index: 100; |
||||
|
height: 70px!important; |
||||
|
width: 70px!important; |
||||
|
position: absolute!important; |
||||
|
top: -45px; |
||||
|
left: 0px; |
||||
|
border: 5px solid #ffffff; |
||||
|
background-color: #fff; |
||||
|
margin: auto; |
||||
|
box-shadow: none!important; |
||||
|
::v-deep .pan-info { |
||||
|
box-shadow: none!important; |
||||
|
} |
||||
|
} |
||||
|
.progress-item { |
||||
|
margin-bottom: 10px; |
||||
|
font-size: 14px; |
||||
|
} |
||||
|
@media only screen and (max-width: 1510px){ |
||||
|
.mallki-text{ |
||||
|
display: none; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
</style> |
@ -0,0 +1,135 @@ |
|||||
|
<template> |
||||
|
<div :class="className" :style="{height:height,width:width}" /> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
const echarts = require('echarts') |
||||
|
require('echarts/theme/macarons') // echarts theme |
||||
|
import resize from './mixins/resize' |
||||
|
|
||||
|
export default { |
||||
|
mixins: [resize], |
||||
|
props: { |
||||
|
className: { |
||||
|
type: String, |
||||
|
default: 'chart' |
||||
|
}, |
||||
|
width: { |
||||
|
type: String, |
||||
|
default: '100%' |
||||
|
}, |
||||
|
height: { |
||||
|
type: String, |
||||
|
default: '350px' |
||||
|
}, |
||||
|
autoResize: { |
||||
|
type: Boolean, |
||||
|
default: true |
||||
|
}, |
||||
|
chartData: { |
||||
|
type: Object, |
||||
|
required: true |
||||
|
} |
||||
|
}, |
||||
|
data() { |
||||
|
return { |
||||
|
chart: null |
||||
|
} |
||||
|
}, |
||||
|
watch: { |
||||
|
chartData: { |
||||
|
deep: true, |
||||
|
handler(val) { |
||||
|
this.setOptions(val) |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
mounted() { |
||||
|
this.$nextTick(() => { |
||||
|
this.initChart() |
||||
|
}) |
||||
|
}, |
||||
|
beforeDestroy() { |
||||
|
if (!this.chart) { |
||||
|
return |
||||
|
} |
||||
|
this.chart.dispose() |
||||
|
this.chart = null |
||||
|
}, |
||||
|
methods: { |
||||
|
initChart() { |
||||
|
this.chart = echarts.init(this.$el, 'macarons') |
||||
|
this.setOptions(this.chartData) |
||||
|
}, |
||||
|
setOptions({ expectedData, actualData } = {}) { |
||||
|
this.chart.setOption({ |
||||
|
xAxis: { |
||||
|
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'], |
||||
|
boundaryGap: false, |
||||
|
axisTick: { |
||||
|
show: false |
||||
|
} |
||||
|
}, |
||||
|
grid: { |
||||
|
left: 10, |
||||
|
right: 10, |
||||
|
bottom: 20, |
||||
|
top: 30, |
||||
|
containLabel: true |
||||
|
}, |
||||
|
tooltip: { |
||||
|
trigger: 'axis', |
||||
|
axisPointer: { |
||||
|
type: 'cross' |
||||
|
}, |
||||
|
padding: [5, 10] |
||||
|
}, |
||||
|
yAxis: { |
||||
|
axisTick: { |
||||
|
show: false |
||||
|
} |
||||
|
}, |
||||
|
legend: { |
||||
|
data: ['expected', 'actual'] |
||||
|
}, |
||||
|
series: [{ |
||||
|
name: 'expected', itemStyle: { |
||||
|
normal: { |
||||
|
color: '#FF005A', |
||||
|
lineStyle: { |
||||
|
color: '#FF005A', |
||||
|
width: 2 |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
smooth: true, |
||||
|
type: 'line', |
||||
|
data: expectedData, |
||||
|
animationDuration: 2800, |
||||
|
animationEasing: 'cubicInOut' |
||||
|
}, |
||||
|
{ |
||||
|
name: 'actual', |
||||
|
smooth: true, |
||||
|
type: 'line', |
||||
|
itemStyle: { |
||||
|
normal: { |
||||
|
color: '#3888fa', |
||||
|
lineStyle: { |
||||
|
color: '#3888fa', |
||||
|
width: 2 |
||||
|
}, |
||||
|
areaStyle: { |
||||
|
color: '#f3f8ff' |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
data: actualData, |
||||
|
animationDuration: 2800, |
||||
|
animationEasing: 'quadraticOut' |
||||
|
}] |
||||
|
}) |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
</script> |
@ -0,0 +1,148 @@ |
|||||
|
<template> |
||||
|
<div :class="className" :style="{height:height,width:width}"/> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
const echarts = require('echarts') |
||||
|
require('./china.js') |
||||
|
require('echarts/theme/macarons') // echarts theme |
||||
|
import resize from './mixins/resize' |
||||
|
|
||||
|
export default { |
||||
|
mixins: [resize], |
||||
|
props: { |
||||
|
className: { |
||||
|
type: String, |
||||
|
default: 'chart' |
||||
|
}, |
||||
|
width: { |
||||
|
type: String, |
||||
|
default: '100%' |
||||
|
}, |
||||
|
height: { |
||||
|
type: String, |
||||
|
default: '300px' |
||||
|
} |
||||
|
}, |
||||
|
data() { |
||||
|
return { |
||||
|
chart: null |
||||
|
} |
||||
|
}, |
||||
|
mounted() { |
||||
|
this.$nextTick(() => { |
||||
|
this.initChart() |
||||
|
}) |
||||
|
}, |
||||
|
beforeDestroy() { |
||||
|
if (!this.chart) { |
||||
|
return |
||||
|
} |
||||
|
this.chart.dispose() |
||||
|
this.chart = null |
||||
|
}, |
||||
|
methods: { |
||||
|
initChart() { |
||||
|
this.chart = echarts.init(this.$el, 'macarons') |
||||
|
|
||||
|
this.chart.setOption({ |
||||
|
title: { |
||||
|
text: '订单量', |
||||
|
subtext: '纯属虚构', |
||||
|
left: 'center' |
||||
|
}, |
||||
|
tooltip: { |
||||
|
trigger: 'item' |
||||
|
}, |
||||
|
legend: { |
||||
|
orient: 'vertical', |
||||
|
left: 'left', |
||||
|
data: ['订单量'] |
||||
|
}, |
||||
|
visualMap: { |
||||
|
type: 'piecewise', |
||||
|
pieces: [ |
||||
|
|
||||
|
{min: 1500}, |
||||
|
{min: 900, max: 1500}, |
||||
|
{min: 310, max: 1000}, |
||||
|
{min: 200, max: 300}, |
||||
|
{min: 10, max: 200, label: '10 到 200(自定义label)'}, |
||||
|
{value: 123, label: '123(自定义特殊颜色)', color: 'grey'}, |
||||
|
{min: 5, max: 5, label: '5(自定义特殊颜色)', color: 'black'}, |
||||
|
{max: 5} |
||||
|
], |
||||
|
color: ['#E0022B', '#E09107', '#A3E00B'] |
||||
|
}, |
||||
|
toolbox: { |
||||
|
show: true, |
||||
|
orient: 'vertical', |
||||
|
left: 'right', |
||||
|
top: 'center', |
||||
|
feature: { |
||||
|
mark: {show: true}, |
||||
|
dataView: {show: true, readOnly: false}, |
||||
|
restore: {show: true}, |
||||
|
saveAsImage: {show: true} |
||||
|
} |
||||
|
}, |
||||
|
roamController: { |
||||
|
show: true, |
||||
|
left: 'right', |
||||
|
mapTypeControl: { |
||||
|
'china': true |
||||
|
} |
||||
|
}, |
||||
|
series: [ |
||||
|
{ |
||||
|
name: '订单量', |
||||
|
type: 'map', |
||||
|
mapType: 'china', |
||||
|
roam: false, |
||||
|
label: { |
||||
|
show: true, |
||||
|
color: 'rgb(249, 249, 249)' |
||||
|
}, |
||||
|
data: [ |
||||
|
{name: '北京', value: 5}, |
||||
|
{name: '天津', value: Math.round(Math.random() * 2000)}, |
||||
|
{name: '上海', value: Math.round(Math.random() * 2000)}, |
||||
|
{name: '重庆', value: Math.round(Math.random() * 2000)}, |
||||
|
{name: '河北', value: 0}, |
||||
|
{name: '河南', value: Math.round(Math.random() * 2000)}, |
||||
|
{name: '云南', value: 123}, |
||||
|
{name: '辽宁', value: 305}, |
||||
|
{name: '黑龙江', value: Math.round(Math.random() * 2000)}, |
||||
|
{name: '湖南', value: 200}, |
||||
|
{name: '安徽', value: Math.round(Math.random() * 2000)}, |
||||
|
{name: '山东', value: Math.round(Math.random() * 2000)}, |
||||
|
{name: '新疆', value: Math.round(Math.random() * 2000)}, |
||||
|
{name: '江苏', value: Math.round(Math.random() * 2000)}, |
||||
|
{name: '浙江', value: Math.round(Math.random() * 2000)}, |
||||
|
{name: '江西', value: Math.round(Math.random() * 2000)}, |
||||
|
{name: '湖北', value: Math.round(Math.random() * 2000)}, |
||||
|
{name: '广西', value: Math.round(Math.random() * 2000)}, |
||||
|
{name: '甘肃', value: Math.round(Math.random() * 2000)}, |
||||
|
{name: '山西', value: Math.round(Math.random() * 2000)}, |
||||
|
{name: '内蒙古', value: Math.round(Math.random() * 2000)}, |
||||
|
{name: '陕西', value: Math.round(Math.random() * 2000)}, |
||||
|
{name: '吉林', value: Math.round(Math.random() * 2000)}, |
||||
|
{name: '福建', value: Math.round(Math.random() * 2000)}, |
||||
|
{name: '贵州', value: Math.round(Math.random() * 2000)}, |
||||
|
{name: '广东', value: Math.round(Math.random() * 2000)}, |
||||
|
{name: '青海', value: Math.round(Math.random() * 2000)}, |
||||
|
{name: '西藏', value: Math.round(Math.random() * 2000)}, |
||||
|
{name: '四川', value: Math.round(Math.random() * 2000)}, |
||||
|
{name: '宁夏', value: Math.round(Math.random() * 2000)}, |
||||
|
{name: '海南', value: Math.round(Math.random() * 2000)}, |
||||
|
{name: '台湾', value: Math.round(Math.random() * 2000)}, |
||||
|
{name: '香港', value: Math.round(Math.random() * 2000)}, |
||||
|
{name: '澳门', value: Math.round(Math.random() * 2000)} |
||||
|
] |
||||
|
} |
||||
|
] |
||||
|
}) |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
</script> |
@ -0,0 +1,181 @@ |
|||||
|
<template> |
||||
|
<el-row :gutter="40" class="panel-group"> |
||||
|
<el-col :xs="12" :sm="12" :lg="6" class="card-panel-col"> |
||||
|
<div class="card-panel" @click="handleSetLineChartData('newVisitis')"> |
||||
|
<div class="card-panel-icon-wrapper icon-people"> |
||||
|
<svg-icon icon-class="peoples" class-name="card-panel-icon" /> |
||||
|
</div> |
||||
|
<div class="card-panel-description"> |
||||
|
<div class="card-panel-text"> |
||||
|
New Visits |
||||
|
</div> |
||||
|
<count-to :start-val="0" :end-val="102400" :duration="2600" class="card-panel-num" /> |
||||
|
</div> |
||||
|
</div> |
||||
|
</el-col> |
||||
|
<el-col :xs="12" :sm="12" :lg="6" class="card-panel-col"> |
||||
|
<div class="card-panel" @click="handleSetLineChartData('messages')"> |
||||
|
<div class="card-panel-icon-wrapper icon-message"> |
||||
|
<svg-icon icon-class="message" class-name="card-panel-icon" /> |
||||
|
</div> |
||||
|
<div class="card-panel-description"> |
||||
|
<div class="card-panel-text"> |
||||
|
Messages |
||||
|
</div> |
||||
|
<count-to :start-val="0" :end-val="81212" :duration="3000" class="card-panel-num" /> |
||||
|
</div> |
||||
|
</div> |
||||
|
</el-col> |
||||
|
<el-col :xs="12" :sm="12" :lg="6" class="card-panel-col"> |
||||
|
<div class="card-panel" @click="handleSetLineChartData('purchases')"> |
||||
|
<div class="card-panel-icon-wrapper icon-money"> |
||||
|
<svg-icon icon-class="money" class-name="card-panel-icon" /> |
||||
|
</div> |
||||
|
<div class="card-panel-description"> |
||||
|
<div class="card-panel-text"> |
||||
|
Purchases |
||||
|
</div> |
||||
|
<count-to :start-val="0" :end-val="9280" :duration="3200" class="card-panel-num" /> |
||||
|
</div> |
||||
|
</div> |
||||
|
</el-col> |
||||
|
<el-col :xs="12" :sm="12" :lg="6" class="card-panel-col"> |
||||
|
<div class="card-panel" @click="handleSetLineChartData('shoppings')"> |
||||
|
<div class="card-panel-icon-wrapper icon-shopping"> |
||||
|
<svg-icon icon-class="shopping" class-name="card-panel-icon" /> |
||||
|
</div> |
||||
|
<div class="card-panel-description"> |
||||
|
<div class="card-panel-text"> |
||||
|
Shoppings |
||||
|
</div> |
||||
|
<count-to :start-val="0" :end-val="13600" :duration="3600" class="card-panel-num" /> |
||||
|
</div> |
||||
|
</div> |
||||
|
</el-col> |
||||
|
</el-row> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
import CountTo from 'CountTo' |
||||
|
|
||||
|
export default { |
||||
|
components: { |
||||
|
CountTo |
||||
|
}, |
||||
|
methods: { |
||||
|
handleSetLineChartData(type) { |
||||
|
this.$emit('handleSetLineChartData', type) |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<style lang="scss" scoped> |
||||
|
.panel-group { |
||||
|
margin-top: 18px; |
||||
|
|
||||
|
.card-panel-col { |
||||
|
margin-bottom: 32px; |
||||
|
} |
||||
|
|
||||
|
.card-panel { |
||||
|
height: 108px; |
||||
|
cursor: pointer; |
||||
|
font-size: 12px; |
||||
|
position: relative; |
||||
|
overflow: hidden; |
||||
|
color: #666; |
||||
|
background: #fff; |
||||
|
box-shadow: 4px 4px 40px rgba(0, 0, 0, .05); |
||||
|
border-color: rgba(0, 0, 0, .05); |
||||
|
|
||||
|
&:hover { |
||||
|
.card-panel-icon-wrapper { |
||||
|
color: #fff; |
||||
|
} |
||||
|
|
||||
|
.icon-people { |
||||
|
background: #40c9c6; |
||||
|
} |
||||
|
|
||||
|
.icon-message { |
||||
|
background: #36a3f7; |
||||
|
} |
||||
|
|
||||
|
.icon-money { |
||||
|
background: #f4516c; |
||||
|
} |
||||
|
|
||||
|
.icon-shopping { |
||||
|
background: #34bfa3 |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.icon-people { |
||||
|
color: #40c9c6; |
||||
|
} |
||||
|
|
||||
|
.icon-message { |
||||
|
color: #36a3f7; |
||||
|
} |
||||
|
|
||||
|
.icon-money { |
||||
|
color: #f4516c; |
||||
|
} |
||||
|
|
||||
|
.icon-shopping { |
||||
|
color: #34bfa3 |
||||
|
} |
||||
|
|
||||
|
.card-panel-icon-wrapper { |
||||
|
float: left; |
||||
|
margin: 14px 0 0 14px; |
||||
|
padding: 16px; |
||||
|
transition: all 0.38s ease-out; |
||||
|
border-radius: 6px; |
||||
|
} |
||||
|
|
||||
|
.card-panel-icon { |
||||
|
float: left; |
||||
|
font-size: 48px; |
||||
|
} |
||||
|
|
||||
|
.card-panel-description { |
||||
|
float: right; |
||||
|
font-weight: bold; |
||||
|
margin: 26px; |
||||
|
margin-left: 0px; |
||||
|
|
||||
|
.card-panel-text { |
||||
|
line-height: 18px; |
||||
|
color: rgba(0, 0, 0, 0.45); |
||||
|
font-size: 16px; |
||||
|
margin-bottom: 12px; |
||||
|
} |
||||
|
|
||||
|
.card-panel-num { |
||||
|
font-size: 20px; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@media (max-width:550px) { |
||||
|
.card-panel-description { |
||||
|
display: none; |
||||
|
} |
||||
|
|
||||
|
.card-panel-icon-wrapper { |
||||
|
float: none !important; |
||||
|
width: 100%; |
||||
|
height: 100%; |
||||
|
margin: 0 !important; |
||||
|
|
||||
|
.svg-icon { |
||||
|
display: block; |
||||
|
margin: 14px auto !important; |
||||
|
float: none !important; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
</style> |
@ -0,0 +1,81 @@ |
|||||
|
<template> |
||||
|
<div :class="className" :style="{height:height,width:width}" /> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
const echarts = require('echarts') |
||||
|
require('echarts/theme/macarons') // echarts theme |
||||
|
import resize from './mixins/resize' |
||||
|
|
||||
|
|
||||
|
|
||||
|
export default { |
||||
|
mixins: [resize], |
||||
|
props: { |
||||
|
className: { |
||||
|
type: String, |
||||
|
default: 'chart' |
||||
|
}, |
||||
|
width: { |
||||
|
type: String, |
||||
|
default: '100%' |
||||
|
}, |
||||
|
height: { |
||||
|
type: String, |
||||
|
default: '300px' |
||||
|
} |
||||
|
}, |
||||
|
data() { |
||||
|
return { |
||||
|
chart: null |
||||
|
} |
||||
|
}, |
||||
|
mounted() { |
||||
|
this.$nextTick(() => { |
||||
|
this.initChart() |
||||
|
}) |
||||
|
}, |
||||
|
beforeDestroy() { |
||||
|
if (!this.chart) { |
||||
|
return |
||||
|
} |
||||
|
this.chart.dispose() |
||||
|
this.chart = null |
||||
|
}, |
||||
|
methods: { |
||||
|
initChart() { |
||||
|
this.chart = echarts.init(this.$el, 'macarons') |
||||
|
|
||||
|
this.chart.setOption({ |
||||
|
tooltip: { |
||||
|
trigger: 'item', |
||||
|
formatter: '{a} <br/>{b} : {c} ({d}%)' |
||||
|
}, |
||||
|
legend: { |
||||
|
left: 'center', |
||||
|
bottom: '10', |
||||
|
data: ['Industries', 'Technology', 'Forex', 'Gold', 'Forecasts'] |
||||
|
}, |
||||
|
series: [ |
||||
|
{ |
||||
|
name: 'WEEKLY WRITE ARTICLES', |
||||
|
type: 'pie', |
||||
|
roseType: 'radius', |
||||
|
radius: [15, 95], |
||||
|
center: ['50%', '38%'], |
||||
|
data: [ |
||||
|
{ value: 320, name: 'Industries' }, |
||||
|
{ value: 240, name: 'Technology' }, |
||||
|
{ value: 149, name: 'Forex' }, |
||||
|
{ value: 100, name: 'Gold' }, |
||||
|
{ value: 59, name: 'Forecasts' } |
||||
|
], |
||||
|
animationEasing: 'cubicInOut', |
||||
|
animationDuration: 2600 |
||||
|
} |
||||
|
] |
||||
|
}) |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
</script> |
@ -0,0 +1,116 @@ |
|||||
|
<template> |
||||
|
<div :class="className" :style="{height:height,width:width}" /> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
import echarts from 'echarts' |
||||
|
require('echarts/theme/macarons') // echarts theme |
||||
|
import resize from './mixins/resize' |
||||
|
|
||||
|
const animationDuration = 3000 |
||||
|
|
||||
|
export default { |
||||
|
mixins: [resize], |
||||
|
props: { |
||||
|
className: { |
||||
|
type: String, |
||||
|
default: 'chart' |
||||
|
}, |
||||
|
width: { |
||||
|
type: String, |
||||
|
default: '100%' |
||||
|
}, |
||||
|
height: { |
||||
|
type: String, |
||||
|
default: '300px' |
||||
|
} |
||||
|
}, |
||||
|
data() { |
||||
|
return { |
||||
|
chart: null |
||||
|
} |
||||
|
}, |
||||
|
mounted() { |
||||
|
this.$nextTick(() => { |
||||
|
this.initChart() |
||||
|
}) |
||||
|
}, |
||||
|
beforeDestroy() { |
||||
|
if (!this.chart) { |
||||
|
return |
||||
|
} |
||||
|
this.chart.dispose() |
||||
|
this.chart = null |
||||
|
}, |
||||
|
methods: { |
||||
|
initChart() { |
||||
|
this.chart = echarts.init(this.$el, 'macarons') |
||||
|
|
||||
|
this.chart.setOption({ |
||||
|
tooltip: { |
||||
|
trigger: 'axis', |
||||
|
axisPointer: { // 坐标轴指示器,坐标轴触发有效 |
||||
|
type: 'shadow' // 默认为直线,可选为:'line' | 'shadow' |
||||
|
} |
||||
|
}, |
||||
|
radar: { |
||||
|
radius: '66%', |
||||
|
center: ['50%', '42%'], |
||||
|
splitNumber: 8, |
||||
|
splitArea: { |
||||
|
areaStyle: { |
||||
|
color: 'rgba(127,95,132,.3)', |
||||
|
opacity: 1, |
||||
|
shadowBlur: 45, |
||||
|
shadowColor: 'rgba(0,0,0,.5)', |
||||
|
shadowOffsetX: 0, |
||||
|
shadowOffsetY: 15 |
||||
|
} |
||||
|
}, |
||||
|
indicator: [ |
||||
|
{ name: 'Sales', max: 10000 }, |
||||
|
{ name: 'Administration', max: 20000 }, |
||||
|
{ name: 'Information Technology', max: 20000 }, |
||||
|
{ name: 'Customer Support', max: 20000 }, |
||||
|
{ name: 'Development', max: 20000 }, |
||||
|
{ name: 'Marketing', max: 20000 } |
||||
|
] |
||||
|
}, |
||||
|
legend: { |
||||
|
left: 'center', |
||||
|
bottom: '10', |
||||
|
data: ['Allocated Budget', 'Expected Spending', 'Actual Spending'] |
||||
|
}, |
||||
|
series: [{ |
||||
|
type: 'radar', |
||||
|
symbolSize: 0, |
||||
|
areaStyle: { |
||||
|
normal: { |
||||
|
shadowBlur: 13, |
||||
|
shadowColor: 'rgba(0,0,0,.2)', |
||||
|
shadowOffsetX: 0, |
||||
|
shadowOffsetY: 10, |
||||
|
opacity: 1 |
||||
|
} |
||||
|
}, |
||||
|
data: [ |
||||
|
{ |
||||
|
value: [5000, 7000, 12000, 11000, 15000, 14000], |
||||
|
name: 'Allocated Budget' |
||||
|
}, |
||||
|
{ |
||||
|
value: [4000, 9000, 15000, 15000, 13000, 11000], |
||||
|
name: 'Expected Spending' |
||||
|
}, |
||||
|
{ |
||||
|
value: [5500, 11000, 12000, 15000, 12000, 12000], |
||||
|
name: 'Actual Spending' |
||||
|
} |
||||
|
], |
||||
|
animationDuration: animationDuration |
||||
|
}] |
||||
|
}) |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
</script> |
@ -0,0 +1,55 @@ |
|||||
|
<template> |
||||
|
<el-table :data="list" style="width: 100%;padding-top: 15px;"> |
||||
|
<el-table-column label="Order_No" min-width="200"> |
||||
|
<template slot-scope="scope"> |
||||
|
{{ scope.row.order_no | orderNoFilter }} |
||||
|
</template> |
||||
|
</el-table-column> |
||||
|
<el-table-column label="Price" width="195" align="center"> |
||||
|
<template slot-scope="scope"> |
||||
|
¥{{ scope.row.price | toThousandFilter }} |
||||
|
</template> |
||||
|
</el-table-column> |
||||
|
<el-table-column label="Status" width="100" align="center"> |
||||
|
<template slot-scope="{row}"> |
||||
|
<el-tag :type="row.status | statusFilter"> |
||||
|
{{ row.status }} |
||||
|
</el-tag> |
||||
|
</template> |
||||
|
</el-table-column> |
||||
|
</el-table> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
import { transactionList } from '@/api/remote-search' |
||||
|
|
||||
|
export default { |
||||
|
filters: { |
||||
|
statusFilter(status) { |
||||
|
const statusMap = { |
||||
|
success: 'success', |
||||
|
pending: 'danger' |
||||
|
} |
||||
|
return statusMap[status] |
||||
|
}, |
||||
|
orderNoFilter(str) { |
||||
|
return str.substring(0, 30) |
||||
|
} |
||||
|
}, |
||||
|
data() { |
||||
|
return { |
||||
|
list: null |
||||
|
} |
||||
|
}, |
||||
|
created() { |
||||
|
this.fetchData() |
||||
|
}, |
||||
|
methods: { |
||||
|
fetchData() { |
||||
|
transactionList().then(response => { |
||||
|
this.list = response.data.items.slice(0, 8) |
||||
|
}) |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
</script> |
File diff suppressed because one or more lines are too long
@ -0,0 +1,55 @@ |
|||||
|
import {debounce} from '@/utils' |
||||
|
|
||||
|
export default { |
||||
|
data() { |
||||
|
return { |
||||
|
$_sidebarElm: null, |
||||
|
$_resizeHandler: null |
||||
|
} |
||||
|
}, |
||||
|
mounted() { |
||||
|
this.$_resizeHandler = debounce(() => { |
||||
|
if (this.chart) { |
||||
|
this.chart.resize() |
||||
|
} |
||||
|
}, 100) |
||||
|
this.$_initResizeEvent() |
||||
|
this.$_initSidebarResizeEvent() |
||||
|
}, |
||||
|
beforeDestroy() { |
||||
|
this.$_destroyResizeEvent() |
||||
|
this.$_destroySidebarResizeEvent() |
||||
|
}, |
||||
|
// to fixed bug when cached by keep-alive
|
||||
|
// https://github.com/PanJiaChen/vue-element-admin/issues/2116
|
||||
|
activated() { |
||||
|
this.$_initResizeEvent() |
||||
|
this.$_initSidebarResizeEvent() |
||||
|
}, |
||||
|
deactivated() { |
||||
|
this.$_destroyResizeEvent() |
||||
|
this.$_destroySidebarResizeEvent() |
||||
|
}, |
||||
|
methods: { |
||||
|
// use $_ for mixins properties
|
||||
|
// https://vuejs.org/v2/style-guide/index.html#Private-property-names-essential
|
||||
|
$_initResizeEvent() { |
||||
|
window.addEventListener('resize', this.$_resizeHandler) |
||||
|
}, |
||||
|
$_destroyResizeEvent() { |
||||
|
window.removeEventListener('resize', this.$_resizeHandler) |
||||
|
}, |
||||
|
$_sidebarResizeHandler(e) { |
||||
|
if (e.propertyName === 'width') { |
||||
|
this.$_resizeHandler() |
||||
|
} |
||||
|
}, |
||||
|
$_initSidebarResizeEvent() { |
||||
|
this.$_sidebarElm = document.getElementsByClassName('sidebar-container')[0] |
||||
|
this.$_sidebarElm && this.$_sidebarElm.addEventListener('transitionend', this.$_sidebarResizeHandler) |
||||
|
}, |
||||
|
$_destroySidebarResizeEvent() { |
||||
|
this.$_sidebarElm && this.$_sidebarElm.removeEventListener('transitionend', this.$_sidebarResizeHandler) |
||||
|
} |
||||
|
} |
||||
|
} |
Loading…
Reference in new issue