You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
205 lines
4.9 KiB
Vue
205 lines
4.9 KiB
Vue
<template>
|
|
<div class="el-statistic">
|
|
<div class="head" v-if="title||$slots.title">
|
|
<slot name="title">
|
|
<span class="title">
|
|
{{ title }}
|
|
</span>
|
|
</slot>
|
|
</div>
|
|
<div class="con">
|
|
<span class="prefix" v-if="prefix||$slots.prefix">
|
|
<slot name="prefix" >
|
|
{{ prefix }}
|
|
</slot>
|
|
</span>
|
|
<span class="number" :style="valueStyle">
|
|
<slot name="formatter"> {{ disposeValue }}</slot>
|
|
</span>
|
|
<span class="suffix" v-if="suffix||$slots.suffix">
|
|
<slot name="suffix">
|
|
{{ suffix }}
|
|
</slot>
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import { isNumber, chain, multiply, padStart, reduce} from 'element-ui/src/utils/lodash';
|
|
export default {
|
|
name: 'ElStatistic',
|
|
data() {
|
|
return {
|
|
disposeValue: '',
|
|
timeTask: null,
|
|
REFRESH_INTERVAL: 1000 / 30
|
|
};
|
|
},
|
|
props: {
|
|
decimalSeparator: {
|
|
type: String,
|
|
default: '.'
|
|
},
|
|
groupSeparator: {
|
|
type: String,
|
|
default: ''
|
|
},
|
|
precision: {
|
|
type: Number,
|
|
default: null
|
|
},
|
|
value: {
|
|
type: [String, Number, Date],
|
|
default: ''
|
|
},
|
|
prefix: {
|
|
type: String,
|
|
default: ''
|
|
},
|
|
suffix: {
|
|
type: String,
|
|
default: ''
|
|
},
|
|
title: {
|
|
type: [String, Number],
|
|
default: ''
|
|
},
|
|
timeIndices: {
|
|
type: Boolean,
|
|
default: false
|
|
},
|
|
valueStyle: {
|
|
type: Object,
|
|
default: function() {
|
|
return {};
|
|
}
|
|
},
|
|
format: {
|
|
type: String,
|
|
default: 'HH:mm:ss:SSS'
|
|
},
|
|
rate: {
|
|
type: Number,
|
|
default: 1000
|
|
}
|
|
},
|
|
created() {
|
|
this.branch();
|
|
},
|
|
watch: {
|
|
value: function() {
|
|
this.branch();
|
|
},
|
|
groupSeparator() {
|
|
this.dispose();
|
|
},
|
|
mulriple() {
|
|
this.dispose();
|
|
}
|
|
},
|
|
methods: {
|
|
branch() {
|
|
let { timeIndices, countDown, dispose} = this;
|
|
if (timeIndices) {
|
|
countDown(this.value.valueOf() || this.value);
|
|
} else {
|
|
dispose();
|
|
}
|
|
},
|
|
magnification(num, mulriple = 1000, groupSeparator = ',') {
|
|
// magnification factor
|
|
const level = String(mulriple).length ;
|
|
return num.replace(new RegExp(`(\\d)(?=(\\d{${level - 1}})+$)`, 'g'), `$1${groupSeparator}`);
|
|
},
|
|
dispose() {
|
|
let { value, rate, groupSeparator } = this;
|
|
if (!isNumber(value)) return false;
|
|
if (this.precision) {
|
|
value = value.toFixed(this.precision);
|
|
}
|
|
let [integer, decimal] = String(value).split('.');
|
|
// 1000 multiplying power
|
|
if (groupSeparator) {
|
|
integer = this.magnification(integer, rate, groupSeparator);
|
|
}
|
|
let result = `${integer}${decimal ? this.decimalSeparator + decimal : ''}`;
|
|
this.disposeValue = result;
|
|
return result;
|
|
},
|
|
diffDate(minuend, subtrahend) {
|
|
return Math.max(minuend - subtrahend, 0);
|
|
},
|
|
suspend(isStop) {
|
|
if (isStop) {
|
|
if (this.timeTask) {
|
|
clearInterval(this.timeTask);
|
|
this.timeTask = null;
|
|
}
|
|
} else {
|
|
this.branch();
|
|
}
|
|
return this.disposeValue;
|
|
},
|
|
formatTimeStr: function(time) {
|
|
let {format} = this;
|
|
const escapeRegex = /\[[^\]]*]/g;
|
|
const keepList = (format.match(escapeRegex) || []).map(str => str.slice(1, -1));
|
|
const timeUnits = [
|
|
['Y', 1000 * 60 * 60 * 24 * 365], // years
|
|
['M', 1000 * 60 * 60 * 24 * 30], // months
|
|
['D', 1000 * 60 * 60 * 24], // days
|
|
['H', 1000 * 60 * 60], // hours
|
|
['m', 1000 * 60], // minutes
|
|
['s', 1000], // seconds
|
|
['S', 1] // million seconds
|
|
];
|
|
let formatText = reduce(
|
|
timeUnits,
|
|
(con, item) => {
|
|
const name = item[0];
|
|
return con.replace(new RegExp(`${name}+`, 'g'), (match) => {
|
|
let sum = chain(time).divide(item[1]).floor(0).value();
|
|
time -= multiply(sum, item[1]);
|
|
return padStart(String(sum), String(match).length, 0);
|
|
});
|
|
},
|
|
format
|
|
);
|
|
let index = 0;
|
|
return formatText.replace(escapeRegex, () => {
|
|
const match = keepList[index];
|
|
index += 1;
|
|
return match;
|
|
});
|
|
},
|
|
stopTime(time) {
|
|
let result = true; // stop
|
|
if (time) {
|
|
this.$emit('change', time);
|
|
result = false;
|
|
} else {
|
|
result = true;
|
|
this.suspend(true);
|
|
this.$emit('finish', true);
|
|
}
|
|
return result;
|
|
},
|
|
countDown(timeVlaue) {
|
|
let {REFRESH_INTERVAL, timeTask, diffDate, formatTimeStr, stopTime, suspend } = this;
|
|
if (timeTask) return;
|
|
let than = this;
|
|
this.timeTask = setInterval(()=> {
|
|
let diffTiem = diffDate(timeVlaue, Date.now());
|
|
than.disposeValue = formatTimeStr(diffTiem);
|
|
stopTime(diffTiem);
|
|
}, REFRESH_INTERVAL);
|
|
this.$once('hook:beforeDestroy', () => {
|
|
suspend(true);
|
|
});
|
|
|
|
}
|
|
}
|
|
};
|
|
</script>
|