技术分类1
constants.js 全局通用js 用来定义全局的变量
export const ConstantSourceType = {
PURCHASE_REWARD: 'Purchase Reward',
PURCHASE_DEDUCTION: 'Consumption Points',
REFUND_REVOKE: 'Refund Revoke Rewards',
REFUND_RECOVER: 'Refund Revoke',
DECLINE_REVOKE: 'Decline Revoke Rewards',
DECLINE_RECOVER: 'Decline Revoke',
SIGN_UP_REWARD: 'Sign Up Reward',
RECOMMEND_REWARD: 'Recommend Reward',
REFERRAL_SIGN_UP_REWARD: 'Invite Friends',
REFERRAL_SIGN_UP_REGISTER_REWARD: 'Invited Sign Up',
REFERRAL_MEMBER_PLACE_ORDER_REWARD: 'Referral Purchase Commission',
PURCHASE_PROMOTION_REWARD: 'Bonus Points',
getSourceType(type) {
switch (type) {
case 'PURCHASE_REWARD':
return ConstantSourceType.PURCHASE_REWARD
case 'PURCHASE_DEDUCTION':
return ConstantSourceType.PURCHASE_DEDUCTION
case 'REFUND_REVOKE':
return ConstantSourceType.REFUND_REVOKE
case 'REFUND_RECOVER':
return ConstantSourceType.REFUND_RECOVER
case 'DECLINE_REVOKE':
return ConstantSourceType.DECLINE_REVOKE
case 'DECLINE_RECOVER':
return ConstantSourceType.DECLINE_RECOVER
case 'SIGN_UP_REWARD':
return ConstantSourceType.SIGN_UP_REWARD
case 'RECOMMEND_REWARD':
return ConstantSourceType.RECOMMEND_REWARD
case 'REFERRAL_SIGN_UP_REWARD':
return ConstantSourceType.REFERRAL_SIGN_UP_REWARD
case 'REFERRAL_SIGN_UP_REGISTER_REWARD':
return ConstantSourceType.REFERRAL_SIGN_UP_REGISTER_REWARD
case 'REFERRAL_MEMBER_PLACE_ORDER_REWARD':
return ConstantSourceType.REFERRAL_MEMBER_PLACE_ORDER_REWARD
case 'PURCHASE_PROMOTION_REWARD':
return ConstantSourceType.PURCHASE_PROMOTION_REWARD
default:
return '---'
}
}
}
技术分类2
echarts的图形显示 data-points.js
/**
* OverView
*/
export class Data_PointsOverview {
constructor() {
this.data = null
}
/**
* 获取区间分布饼图配置
*/
getDistributionChartOptions(dataList) {
return {
tooltip: {
show: true,
trigger: 'item',
formatter: '{a} <br/>{b} : {c} ({d}%)'
},
legend: {
orient: 'vertical',
right: 30,
top: 0,
bottom: 20,
itemWidth: 5,
itemHeight: 5,
itemGap: 10,
textStyle: {
color: '#909399',
fontWeight: 'bolder'
}
},
series: [
{
name: 'Point Outstanding',
type: 'pie',
radius: ['40%', '80%'],
avoidLabelOverlap: false,
itemStyle: {
borderRadius: 10,
borderColor: '#fff',
borderWidth: 2
},
center: ['30%', '45%'],
label: {
show: false,
position: 'center'
},
color: [
'rgb(226,239,253)', 'rgb(204,228,252)', 'rgb(175,215,255)', 'rgb(139,196,255)', 'rgb(99,175,255)',
'rgb(61,156,255)', 'rgb(55,132,255)', 'rgb(45,105,222)', 'rgb(34,83,176)', 'rgb(22,62,129)'
],
data: dataList
}
]
}
}
}
/**
* trend
*/
export class Data_PointsTrend {
constructor() {
this.data = null
}
/**
* 积分趋势折线图配置项
*/
getTrendChartOptions(dateArr, pointsIssuedArr, pointsUsedArr, interactiveMembersArr, usedPercentageArr) {
return {
grid: {
left: '20px',
right: '20px',
bottom: '20px',
top: '40px',
containLabel: true
},
legend: {
data: ['Points Issued', 'Points Used', 'Interactive Members', 'Used Percentage'],
left: 20,
selected: {
// 选中'系列1'
'Points Issued': true,
// 不选中'系列2'
'Points Used': false,
'Interactive Members': false,
'Used Percentage': false
},
icon: 'roundRect',
show: true
},
tooltip: {
trigger: 'axis',
textStyle: {
color: 'rgba(48,49,51)'
},
backgroundColor: 'rgba(255,255,255,0.9)',
borderColor: '#cccccc',
borderWidth: 1,
padding: [20],
formatter: function(params) {
var str = ''
str += '<div>' + params[0].name + '</div>'
for (var i = 0; i < params.length; i++) {
if (params[i].seriesName === 'Used Percentage') {
str += '<span style="display:inline-block;margin-right:5px;border-radius:10px;width:10px;height:10px;background-color:' + params[i].color + ';"></span>' + params[i].seriesName + '</span> <span style="display:inline-block;font-weight: bold;min-width: 46px;text-align: right;">' + (params[i].data + '%') + '</span><br>'
} else {
str += '<span style="display:inline-block;margin-right:5px;border-radius:10px;width:10px;height:10px;background-color:' + params[i].color + ';"></span>' + params[i].seriesName + '</span> <span style="display:inline-block;font-weight: bold;min-width: 46px;text-align: right;">' + (params[i].data) + '</span><br>'
}
}
console.log(str)
return str
}
},
xAxis: [
{
type: 'category',
boundaryGap: false,
axisLine: {
lineStyle: {
color: '#EBEBEB'
}
},
axisLabel: {
color: '#9E9E9E'
},
data: dateArr
}
],
yAxis: [
{
type: 'value',
splitNumber: 4,
axisLine: {
lineStyle: {
color: '#EBEBEB',
width: 0
}
},
splitLine: {
lineStyle: {
color: '#EBEBEB'
}
},
axisLabel: {
color: '#9E9E9E',
formatter: '{value}'
}
},
{
type: 'value',
splitNumber: 4,
axisLine: {
lineStyle: {
color: '#EBEBEB',
width: 0
}
},
splitLine: {
lineStyle: {
color: '#EBEBEB'
}
},
axisLabel: {
color: '#9E9E9E',
formatter: '{value}%'
}
}
],
series: [
{
name: 'Points Issued',
type: 'line',
smooth: true,
lineStyle: {
color: '#ff4848'
},
showSymbol: false,
itemStyle: {
color: '#ff4848'
},
data: pointsIssuedArr
},
{
name: 'Points Used',
type: 'line',
smooth: true,
lineStyle: {
color: '#2a83ff'
},
itemStyle: {
color: '#2a83ff'
},
showSymbol: false,
data: pointsUsedArr
},
{
name: 'Interactive Members',
type: 'line',
smooth: true,
lineStyle: {
color: '#FF9b00'
},
itemStyle: {
color: '#FF9b00'
},
showSymbol: false,
data: interactiveMembersArr
},
{
name: 'Used Percentage',
type: 'line',
smooth: true,
lineStyle: {
color: '#00c290'
},
yAxisIndex: 1,
itemStyle: {
color: '#00c290'
},
showSymbol: false,
data: usedPercentageArr
}
]
}
}
/**
* 积分区间饼图配置项
*/
getDistributionOptions(dataList, isUsed) {
return {
tooltip: {
show: true,
trigger: 'item',
formatter: '{a} <br/>{b} : {c} ({d}%)'
},
legend: {
orient: 'vertical',
right: 10,
top: 0,
bottom: 20,
itemWidth: 5,
itemHeight: 5,
itemGap: 8,
textStyle: {
color: '#909399',
fontWeight: 'bolder'
}
},
series: [
{
name: isUsed ? 'Point Used' : 'Issued',
type: 'pie',
radius: ['40%', '80%'],
avoidLabelOverlap: false,
itemStyle: {
borderRadius: 10,
borderColor: '#fff',
borderWidth: 2
},
center: ['30%', '45%'],
label: {
show: false,
position: 'center'
},
color: [
'rgb(55,132,255)', 'rgb(61,156,255)', 'rgb(99,175,255)', 'rgb(139,196,255)', 'rgb(175,215,255)',
'rgb(204,228,252)', 'rgb(226,239,253)'
],
data: dataList
}
]
}
}
}
1 首先定义一个 div
<div ref="distributionChart" class="chart-box" style="width: 100%" />
2 定义模型数据
distributionChart: undefined,
3 初始化 demo
this.distributionChart = echarts.init(this.$refs.distributionChart)
4 设置数据
this.distributionChart.setOption(this.overviewData.getDistributionChartOptions(this.memberPointOutstandingDistribution.outstandingDistributionList))
5 跟随浏览器只有缩放
this.__resizeChartHandler = debounce(() => {
this.distributionChart.resize()
}, 50)
window.addEventListener('resize', this.__resizeChartHandler)
import { debounce } from '@/utils'
/**
* @param {Function} func
* @param {number} wait
* @param {boolean} immediate
* @return {*}
*/
export function debounce(func, wait, immediate) {
let timeout, args, context, timestamp, result
const later = function() {
// 据上一次触发时间间隔
const last = +new Date() - timestamp
// 上次被包装函数被调用时间间隔 last 小于设定时间间隔 wait
if (last < wait && last > 0) {
timeout = setTimeout(later, wait - last)
} else {
timeout = null
// 如果设定为immediate===true,因为开始边界已经调用过了此处无需调用
if (!immediate) {
result = func.apply(context, args)
if (!timeout) context = args = null
}
}
}
技术分类三 自定普通组件1
<template>
<div id="panel_item">
<el-card>
<el-row class="text_c title">
{{ title }}
<el-tooltip class="item" effect="dark" :content="tip" placement="bottom-end">
<i v-if="tip" class="el-icon-question"></i>
</el-tooltip>
</el-row>
<el-row class="text_c value">
<count-to :start-val="0.00" :end-val="value" :duration="1000" :decimals="decimals" />
<span v-if="unit">{{ unit }}</span>
</el-row>
<el-row class="price">
<el-row v-if="price" class="text_c">
=$
<count-to :start-val="0.00" :end-val="price" :duration="1000" :decimals="decimals" />
</el-row>
</el-row>
</el-card>
</div>
</template>
<script>
import CountTo from 'vue-count-to'
export default {
name: 'PanelItem',
/**
* 组件
* *****************************************************************************************************************
*/
components: {
CountTo
},
/**
* 外部变量
* *****************************************************************************************************************
*/
props: {
title: {
type: String,
default: 'Panel ###'
},
value: {
type: Number,
default: 0
},
decimals: {
type: Number,
default: 0
},
unit: {
type: String,
default: null
},
price: {
type: Number,
default: 0
},
tip: {
type: String,
default: null
}
},
/**
* 数据定义
* *****************************************************************************************************************
*/
data() {
return {
REF: {}
}
},
/**
* 计算属性
* *****************************************************************************************************************
*/
computed: {},
/**
* 挂载完成
* *****************************************************************************************************************
*/
mounted() {
},
/**
* 自定义方法
* *****************************************************************************************************************
*/
methods: {}
}
</script>
<style lang="scss" scoped>
</style>
<style lang="scss">
#panel_item {
.el-card__body {
padding: 0;
}
.title {
height: 20px;
line-height: 20px;
margin-top: 10px;
}
.value {
font-size: 25px;
font-weight: 800;
line-height: 40px;
height: 40px;
}
.price {
margin-bottom: 10px;
line-height: 10px;
height: 10px;
color: #909399;
font-size: 12px;
}
}
</style>
!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define("CountTo",[],e):"object"==typeof exports?exports.CountTo=e():t.CountTo=e()}(this,function(){return function(t){function e(n){if(i[n])return i[n].exports;var a=i[n]={i:n,l:!1,exports:{}};return t[n].call(a.exports,a,a.exports,e),a.l=!0,a.exports}var i={};return e.m=t,e.c=i,e.i=function(t){return t},e.d=function(t,i,n){e.o(t,i)||Object.defineProperty(t,i,{configurable:!1,enumerable:!0,get:n})},e.n=function(t){var i=t&&t.__esModule?function(){return t.default}:function(){return t};return e.d(i,"a",i),i},e.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},e.p="/dist/",e(e.s=2)}([function(t,e,i){var n=i(4)(i(1),i(5),null,null);t.exports=n.exports},function(t,e,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var n=i(3);e.default={props:{startVal:{type:Number,required:!1,default:0},endVal:{type:Number,required:!1,default:2017},duration:{type:Number,required:!1,default:3e3},autoplay:{type:Boolean,required:!1,default:!0},decimals:{type:Number,required:!1,default:0,validator:function(t){return t>=0}},decimal:{type:String,required:!1,default:"."},separator:{type:String,required:!1,default:","},prefix:{type:String,required:!1,default:""},suffix:{type:String,required:!1,default:""},useEasing:{type:Boolean,required:!1,default:!0},easingFn:{type:Function,default:function(t,e,i,n){return i*(1-Math.pow(2,-10*t/n))*1024/1023+e}}},data:function(){return{localStartVal:this.startVal,displayValue:this.formatNumber(this.startVal),printVal:null,paused:!1,localDuration:this.duration,startTime:null,timestamp:null,remaining:null,rAF:null}},computed:{countDown:function(){return this.startVal>this.endVal}},watch:{startVal:function(){this.autoplay&&this.start()},endVal:function(){this.autoplay&&this.start()}},mounted:function(){this.autoplay&&this.start(),this.$emit("mountedCallback")},methods:{start:function(){this.localStartVal=this.startVal,this.startTime=null,this.localDuration=this.duration,this.paused=!1,this.rAF=(0,n.requestAnimationFrame)(this.count)},pauseResume:function(){this.paused?(this.resume(),this.paused=!1):(this.pause(),this.paused=!0)},pause:function(){(0,n.cancelAnimationFrame)(this.rAF)},resume:function(){this.startTime=null,this.localDuration=+this.remaining,this.localStartVal=+this.printVal,(0,n.requestAnimationFrame)(this.count)},reset:function(){this.startTime=null,(0,n.cancelAnimationFrame)(this.rAF),this.displayValue=this.formatNumber(this.startVal)},count:function(t){this.startTime||(this.startTime=t),this.timestamp=t;var e=t-this.startTime;this.remaining=this.localDuration-e,this.useEasing?this.countDown?this.printVal=this.localStartVal-this.easingFn(e,0,this.localStartVal-this.endVal,this.localDuration):this.printVal=this.easingFn(e,this.localStartVal,this.endVal-this.localStartVal,this.localDuration):this.countDown?this.printVal=this.localStartVal-(this.localStartVal-this.endVal)*(e/this.localDuration):this.printVal=this.localStartVal+(this.localStartVal-this.startVal)*(e/this.localDuration),this.countDown?this.printVal=this.printVal<this.endVal?this.endVal:this.printVal:this.printVal=this.printVal>this.endVal?this.endVal:this.printVal,this.displayValue=this.formatNumber(this.printVal),e<this.localDuration?this.rAF=(0,n.requestAnimationFrame)(this.count):this.$emit("callback")},isNumber:function(t){return!isNaN(parseFloat(t))},formatNumber:function(t){t=t.toFixed(this.decimals),t+="";var e=t.split("."),i=e[0],n=e.length>1?this.decimal+e[1]:"",a=/(\d+)(\d{3})/;if(this.separator&&!this.isNumber(this.separator))for(;a.test(i);)i=i.replace(a,"$1"+this.separator+"$2");return this.prefix+i+n+this.suffix}},destroyed:function(){(0,n.cancelAnimationFrame)(this.rAF)}}},function(t,e,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var n=i(0),a=function(t){return t&&t.__esModule?t:{default:t}}(n);e.default=a.default,"undefined"!=typeof window&&window.Vue&&window.Vue.component("count-to",a.default)},function(t,e,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var n=0,a="webkit moz ms o".split(" "),r=void 0,o=void 0;if("undefined"==typeof window)e.requestAnimationFrame=r=function(){},e.cancelAnimationFrame=o=function(){};else{e.requestAnimationFrame=r=window.requestAnimationFrame,e.cancelAnimationFrame=o=window.cancelAnimationFrame;for(var s=void 0,u=0;u<a.length&&(!r||!o);u++)s=a[u],e.requestAnimationFrame=r=r||window[s+"RequestAnimationFrame"],e.cancelAnimationFrame=o=o||window[s+"CancelAnimationFrame"]||window[s+"CancelRequestAnimationFrame"];r&&o||(e.requestAnimationFrame=r=function(t){var e=(new Date).getTime(),i=Math.max(0,16-(e-n)),a=window.setTimeout(function(){t(e+i)},i);return n=e+i,a},e.cancelAnimationFrame=o=function(t){window.clearTimeout(t)})}e.requestAnimationFrame=r,e.cancelAnimationFrame=o},function(t,e){t.exports=function(t,e,i,n){var a,r=t=t||{},o=typeof t.default;"object"!==o&&"function"!==o||(a=t,r=t.default);var s="function"==typeof r?r.options:r;if(e&&(s.render=e.render,s.staticRenderFns=e.staticRenderFns),i&&(s._scopeId=i),n){var u=Object.create(s.computed||null);Object.keys(n).forEach(function(t){var e=n[t];u[t]=function(){return e}}),s.computed=u}return{esModule:a,exports:r,options:s}}},function(t,e){t.exports={render:function(){var t=this,e=t.$createElement;return(t._self._c||e)("span",[t._v("\n "+t._s(t.displayValue)+"\n")])},staticRenderFns:[]}}])});
//# sourceMappingURL=vue-count-to.min.js.map
2 父组件引用
<panel-item
title="Point Outstanding" :value="Number(memberPointOutstandingDistribution.pointsOutstanding)"
:price="Number(memberPointOutstandingDistribution.pointsAmount)">
</panel-item>
import PanelItem from '../components/panel-item'
components: {
PanelItem,
ProgressBar,
TrendAnalysis
},
4 自定义 比例的条做一个 由左到右 扩展的动画 组件
<template>
<div id="progress_bar">
<el-row ref="container">
<el-col class="line_box" :style="lineWidth"></el-col>
<el-col v-if="showText" class="label_box">
{{ value }}%
</el-col>
</el-row>
</div>
</template>
<script>
export default {
name: 'ProgressBar',
/**
* 组件
* *****************************************************************************************************************
*/
components: {},
/**
* 外部变量
* *****************************************************************************************************************
*/
props: {
// 范围 0 - 100
progress: {
type: Number,
default: 0
},
// 是否显示进度文字
showText: {
type: Boolean,
default: true
}
},
/**
* 数据定义
* *****************************************************************************************************************
*/
data() {
return {
maxValue: 100,
value: 0,
REF: {}
}
},
/**
* 计算属性
* *****************************************************************************************************************
*/
computed: {
lineWidth() {
let containerWidth = this.getWidth()
if (containerWidth > 65) {
containerWidth = containerWidth - 65
}
const lineWidth = (this.value / 100) * containerWidth
return 'width: ' + lineWidth + 'px;'
}
},
/**
* 属性监听
* *****************************************************************************************************************
*/
watch: {
},
/**
* 挂载完成
* *****************************************************************************************************************
*/
mounted() {
this.getWidth()
if (this.value !== this.progress) {
this.value = 0
this.increase()
}
},
/**
* 自定义方法
* *****************************************************************************************************************
*/
methods: {
/**
* 自增
*/
increase() {
this.value = 0
const timer = setInterval(() => {
this.value = this.value + 1
if (this.value >= this.progress) {
this.value = this.progress
clearInterval(timer)
}
}, 10)
},
/**
* 获取容器宽度
*/
getWidth() {
if (this.$refs.container) {
return this.$refs.container.$el.offsetWidth
} else {
return 0
}
}
}
}
</script>
<style lang="scss" scoped>
</style>
<style lang="scss">
#progress_bar {
.line_box {
//width: calc(100% - 65px);
width: 0;
height: 10px;
background-color: #1890ff;
line-height: 20px;
margin-top: 6px;
}
.label_box {
width: 60px;
margin-left: 5px;
line-height: 20px;
}
}
</style>