Commit ab57751f by liuchenxi

update: 触达效果

parent c1107728
<template>
<div class="layout-container">
<div class="layout-container" :style="{ height: bodyHeight + 'px' }">
<vue-gic-header class="user-header-pop" style="z-index: 1999;" :projectName="projectName" :collapseFlag="collapseFlag" @collapseTag="collapseTagHandler" @toRouterView="toRouterView"></vue-gic-header>
<div class="layout">
<aside-menu class="layout-left" v-if="asideShow" :projectName="projectName" :leftModulesName="leftModulesName" :collapseFlag.sync="collapseFlag"></aside-menu>
......@@ -10,8 +10,11 @@
<el-breadcrumb-item :class="{ 'no-link': !v.path }" v-for="(v, i) in breadcrumb" :key="i" :to="{ path: v.path }">{{ v.name }}</el-breadcrumb-item>
</el-breadcrumb>
<h3>
<span>{{ contentTitle }}</span>
<div v-html="layoutTips" class="layout--tips--wrap"></div>
<div>
<span>{{ contentTitle }}</span>
<div v-html="layoutTips" class="layout--tips--wrap"></div>
</div>
<div><span class="intro" @click="() => (drawer = true)">指标说明</span></div>
</h3>
</div>
<div class="layout-content__wrap">
......@@ -22,20 +25,25 @@
<vue-gic-footer></vue-gic-footer>
</div>
</div>
<description :drawer.sync="drawer" :direction="direction" :contentTitle="contentTitle" />
</div>
</template>
<script>
import asideMenu from '../aside-menu';
import description from '@/views/ecm/touch-components/description.vue';
export default {
components: {
asideMenu
asideMenu,
description
},
data() {
return {
collapseFlag: false,
projectName: 'marketing',
leftModulesName: '公众号配置',
bodyHeight: 0
bodyHeight: 0,
drawer: false,
direction: 'rtl'
};
},
mounted() {
......@@ -72,12 +80,19 @@ export default {
collapseTagHandler(val) {
this.collapseFlag = val;
}
},
watch: {
$route: {
handler: function() {
this.drawer = false;
}
}
}
};
</script>
<style lang="scss">
.layout-container {
height: 100vh;
height: 100%;
display: flex;
}
.layout {
......@@ -95,7 +110,6 @@ export default {
position: fixed;
left: 0;
z-index: 9;
height: 100%;
}
&-right {
position: relative;
......@@ -127,6 +141,19 @@ export default {
font-size: 20px;
padding: 24px 0;
font-weight: 500;
display: flex;
justify-content: space-between;
.intro {
width: 64px;
height: 22px;
font-size: 16px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #1890ff;
line-height: 22px;
cursor: pointer;
padding-right: 30px;
}
}
}
&-content__wrap {
......
......@@ -65,6 +65,24 @@ export default {
path: '/ecm/list',
type: 'currrent'
}
},
{
path: 'touch/:id',
name: '触达效果',
component: () => import(/* webpackChunkName: "ecm" */ '../../views/ecm/touch-effect.vue'),
meta: {
path: '/ecm/list',
type: 'info'
}
},
{
path: 'clue',
name: '线索页',
component: () => import(/* webpackChunkName: "ecm" */ '../../views/ecm/touch-clue.vue'),
meta: {
path: '/ecm/list',
type: 'info'
}
}
]
};
......
......@@ -43,6 +43,17 @@ export const exportBatchSendDetails = config.api + PREFIX + 'export-batch-send-d
// 智能营销--实时人员列表--导出csv
export const exportCurrentSendDetails = config.api + PREFIX + 'export-current-send-details';
// 智能营销--触达效果
export const ecmTouchEffectColumnDiagram = params => requests(PREFIX + 'ecmTouchEffectColumnDiagram', params);
export const ecmTouchEffectTable = params => requests(PREFIX + 'ecmTouchEffectTable', params);
export const ecmTouchEffectFunnelChart = params => requests(PREFIX + 'ecmTouchEffectFunnelChart', params);
// 智能营销--导购线索
export const ecmGuideCluesColumnDiagram = params => requests(PREFIX + 'ecmGuideCluesColumnDiagram', params);
export const ecmGuideCluesTable = params => requests(PREFIX + 'ecmGuideCluesTable', params);
// 智能营销--后台线索
export const ecmHeadCluesColumnDiagram = params => requests(PREFIX + 'ecmHeadCluesColumnDiagram', params);
export const ecmHeadGuideCluesTable = params => requests(PREFIX + 'ecmHeadGuideCluesTable', params);
export const getUseStoredFalg = params => requests(PREFIX + 'get-ecm-store-flag', params);
export const getXsxsFalg = params => requests(PREFIX + 'get-xsxs-open-flag', params);
......@@ -23,7 +23,7 @@
</template>
</el-table-column>
<el-table-column min-width="100" align="left" prop="creatorName" label="创建人" v-if="$store.state.marketing.openFlag"></el-table-column>
<el-table-column label="操作" align="left" width="220" fixed="right">
<el-table-column label="操作" align="left" width="260" fixed="right">
<template slot-scope="scope">
<template v-if="scope.row.canEdit !== false">
<el-button type="text" v-if="scope.row.effectType == 0 || scope.row.effectType == 1" @click="editData(scope.row)">编辑</el-button>
......@@ -36,6 +36,7 @@
<el-button type="text">删除</el-button>
</dm-delete>
<el-button type="text" @click="toRecord(scope.row)">记录</el-button>
<el-button type="text" @click="toTouch(scope.row)">触达效果</el-button>
</template>
</el-table-column>
</el-table>
......@@ -46,13 +47,31 @@
import activitySelect from '@/components/activity-select/index.vue';
import { loadEcmList, deleteEcm, offlineEcmPlan, getUseStoredFalg } from '@/service/api/ecmApi.js';
import { formatDateTimeByType } from '@/utils/index.js';
const marketingTypeOptions = [{ value: '', label: '所有发送类型' }, { value: 'card', label: '卡券营销' }, { value: 'message', label: '短信营销' }, { value: 'teletext', label: '图文营销' }, { value: 'text', label: '文本营销' }, { value: 'teltask', label: '话务' }, { value: 'image', label: '微信图片' }]; // eslint-disable-line
const marketingTypeOptions = [
{ value: '', label: '所有发送类型' },
{ value: 'card', label: '卡券营销' },
{ value: 'message', label: '短信营销' },
{ value: 'teletext', label: '图文营销' },
{ value: 'text', label: '文本营销' },
{ value: 'teltask', label: '话务' },
{ value: 'image', label: '微信图片' }
]; // eslint-disable-line
export default {
name: 'ecm',
data() {
return {
effectTypeOption: [{ value: '', label: '所有时效' }, { value: 0, label: '触点' }, { value: 1, label: '重复' }, { value: 2, label: '单次' }], // eslint-disable-line
onlineOptions: [{ value: '', label: '所有上线状态' }, { value: 0, label: '待上线' }, { value: 1, label: '已上线' }, { value: 2, label: '已下线' }], // eslint-disable-line
effectTypeOption: [
{ value: '', label: '所有时效' },
{ value: 0, label: '触点' },
{ value: 1, label: '重复' },
{ value: 2, label: '单次' }
], // eslint-disable-line
onlineOptions: [
{ value: '', label: '所有上线状态' },
{ value: 0, label: '待上线' },
{ value: 1, label: '已上线' },
{ value: 2, label: '已下线' }
], // eslint-disable-line
marketingTypeOptions,
listParams: {
effectType: '', // 全部失效的默认值是-1,提交时判断''改为-1
......@@ -121,7 +140,11 @@ export default {
}
return result;
}
}
},
{ label: '营销人数', prop: 'ecmMemberNum', minWidth: '120', align: 'left' },
{ label: '触达人数', prop: 'ecmSuccessNum', minWidth: '120', align: 'left' },
{ label: '转换人数', prop: 'ecmTranNum', minWidth: '120', align: 'left' },
{ label: '线索转化收益', prop: 'ecmTranIncome', minWidth: '120', align: 'left' }
],
tableList: []
};
......@@ -137,7 +160,10 @@ export default {
});
this.loadEcmList();
this.$store.commit('aside_handler', false);
this.$store.commit('mutations_breadcrumb', [{ name: '营销管理', path: '' }, { name: '智能营销', path: '/ecm' }]); // eslint-disable-line
this.$store.commit('mutations_breadcrumb', [
{ name: '营销管理', path: '' },
{ name: '智能营销', path: '/ecm' }
]); // eslint-disable-line
},
methods: {
search() {
......@@ -173,6 +199,10 @@ export default {
const prefix = row.effectType == 1 ? 'batchlist' : row.effectType == 2 ? 'oncelist' : 'currentlist';
this.$router.push({ path: `/ecm/${prefix}/${row.ecmPlanId}`, query: { name: row.ecmPlanName } });
},
// 触达效果
toTouch(row) {
this.$router.push({ path: `/ecm/touch/${row.ecmPlanId}`, query: { name: row.ecmPlanName } });
},
// 删除
async delData(row) {
try {
......
<template>
<!--文字说明-->
<el-drawer title="数据指标说明" :visible.sync="drawer" :direction="direction" custom-class="touch_drawer h650" v-if="contentTitle == '触达效果'">
<ul class="content">
<li>数据更新频率:1天1次</li>
<li>
<span class="squre"></span>
<div class="text">
<p>1.转化效果趋势图</p>
<p>按日展示。当天转化人数可能是因为之前的触达影响的,所以当日触达转化额人数可能大于触达人数。</p>
</div>
</li>
<li>
<span class="squre"></span>
<div class="text">
<p>2.计划整体效果</p>
<p>配置了参照组的,展示参照组转化情况,即计划中设定的非触达人群的转化情况;</p>
</div>
</li>
<li>
<span class="squre"></span>
<div class="text">
<p>3.线索转化对比</p>
<p>导购线索:计划中触达到门店导购端的都归入导购线索,包括话务、企微任务;<br />后台线索:计划中非导购线索的触达,包括图文、文本、小程序、图片、卡券等。</p>
</div>
</li>
<li>
<span class="squre"></span>
<div class="text">
<p>4.转化收益</p>
<p>
① 触达后产生的消费在触达收益计算有效期内的,计入转化效益,有效期见计划配置;<br />
② 导购和后台线索均有触达,消费在两者触达的有效期内的,收益归给导购线索;<br />
③ 一个触达转化消费,在多个导购触达任务的收益计算有效期内的,该笔转化只记给第一个触达任务;<br />
④ 转化收益只计销售单,不看退货单和换货单;金额是应付还是实付看ERP传入的值。<br />
⑤『触达率』:触达人数 / 计划触达人数 <br />
⑥『转化率』:转化人数 / 触达人数
</p>
</div>
</li>
</ul>
</el-drawer>
<el-drawer title="【导购线索】说明" :visible.sync="drawer" :direction="direction" custom-class="touch_drawer h850" v-else-if="contentTitle == '导购线索'">
<ul class="content">
<li>数据更新频率:1天1次</li>
<!-- <li>导购线索:计划中触达到门店导购端的都归入导购线索,包括话务、企微任务。</li>
-->
<li>
<span class="squre"></span>
<div class="text">
<p>1.导购线索</p>
<p>计划中触达到门店导购端的都归入导购线索,包括话务、企微任务。</p>
</div>
</li>
<li>
<span class="squre"></span>
<div class="text">
<p>2.导购线索概况 - 趋势图</p>
<p>按日展示。当天转化人数可能是因为之前的触达影响的,所以当日触达转化额人数可能大于触达人数。</p>
</div>
</li>
<li>
<span class="squre"></span>
<div class="text">
<p>3. 导购线索转化</p>
<p>
①『计划触达人数』: 新建计划时确定的要通过导购线索进行触达的人数;区域、门店粒度的为任务下发人数。<br />
②『任务完成率』: 导购任务完成数 / 任务总数,任务完成数不含放弃数。<br />
③『任务总数』: 下发的任务总数。一些任务可能下发失败,故任务人数可能小于计划触达人数;1个导购可能被触发多个任务,任务总数记多个,和人数不一样。<br />
④『触达人数』:任务触达的人数<br />
⑤『触达率』:『触达人数』/『计划触达人数』<br />
⑥『转化人数』:通过导购线索触达,且触达的会员在触达效益计算有效期内前来消费的人数。多个导购线索任务触达的,转化只记在首个触达任务上<br />
⑦『转化率』:『转化人数』/『触达人数』<br />
⑧『转化订单数』:通过导购线索触达,且触达的会员在触达效益计算有效期内前来消费的订单,只看销售单<br />
⑨『转化收益』:转化的金额,只计销售单,不看退货单和换货单;金额是应付还是实付看ERP传入的值。
</p>
</div>
</li>
<li>
<span class="squre"></span>
<div class="text">
<p>4.区域详情</p>
<p>
任务完成情况:不同任务的完成情况,任务完成数不含放弃。<br />
触达效果:导购线索中不同任务完成方式的触达转化情况。话务任务暂不区分私人电话和企业电话,所以完成方式为 话务。<br />
注意:区域详情合计按任务门店统计汇总,上方计划整体数据以企业粒度单独计算,数据不完全一致。
</p>
</div>
</li>
</ul>
</el-drawer>
<el-drawer title="【导购线索】说明" :visible.sync="drawer" :direction="direction" custom-class="touch_drawer h670" v-else-if="contentTitle == '后台线索'">
<ul class="content">
<li>数据更新频率:1天1次</li>
<!-- <li>导购线索:计划中触达到门店导购端的都归入导购线索,包括话务、企微任务。</li>
-->
<li>
<span class="squre"></span>
<div class="text">
<p>1.后台线索</p>
<p>计划中非导购线索的触达,包括图文、文本、小程序、图片、卡券等。</p>
</div>
</li>
<li>
<span class="squre"></span>
<div class="text">
<p>2.后台线索概况 - 趋势图</p>
<p>按日展示。当天转化人数可能是因为之前的触达影响的,所以当日触达转化额人数可能大于触达人数。</p>
</div>
</li>
<li>
<span class="squre"></span>
<div class="text">
<p>3. 后台线索转化</p>
<p>
①『计划触达人数』: 新建计划时确定的要通过后台线索进行触达的人数<br />
②『触达人数』:任务触达的人数<br />
③『触达率』:『触达人数』/『计划触达人数』<br />
④『转化人数』:通过后台线索触达,且触达的会员在触达效益计算有效期内前来消费的人数。导购和后台线索均有触达,消费在两者触达的有效期内的,收益归给导购线索;<br />
⑤『转化率』:『转化人数』/『触达人数』<br />
⑥『转化订单数』:通过后台线索触达,且触达的会员在触达效益计算有效期内前来消费的订单,只看销售单<br />
⑦『转化收益』:转化的金额,只计销售单,不看退货单和换货单;金额是应付还是实付看ERP传入的值。
</p>
</div>
</li>
<li>
<span class="squre"></span>
<div class="text">
<p>4.区域详情</p>
<p>区域粒度的『触达人数』和『触达率』按服务门店统计,其余转化信息按消费门店统计。</p>
</div>
</li>
</ul>
</el-drawer>
</template>
<script>
export default {
props: {
drawer: {
type: Boolean,
default: false
},
direction: {
type: String,
default: 'rtl'
},
contentTitle: String
},
watch: {
drawer(newVal) {
this.$emit('update:drawer', newVal);
}
}
};
</script>
<style lang="scss">
.h850 {
height: 850px !important;
}
.h650 {
height: 650px !important;
}
.h670 {
height: 670px !important;
}
.touch_drawer {
width: 395px !important;
background: #ffffff;
box-shadow: 0px 10px 20px 0px rgba(0, 0, 0, 0.15) !important;
border-radius: 2px !important;
border: 1px solid #dcdfe6 !important;
position: absolute;
top: 64px !important;
right: 24px !important;
padding: 14px 24px 21px 20px;
.el-drawer__header {
padding: 0;
margin-bottom: 22px;
font-size: 16px;
font-family: PingFangSC-Medium, PingFang SC;
color: #303133;
line-height: 22px;
span {
font-weight: 600;
}
}
.content {
li {
display: flex;
margin-bottom: 20px;
font-size: 13px;
font-weight: 400;
color: #606266;
font-family: PingFangSC-Regular, PingFang SC;
line-height: 20px;
&:last-child {
margin-bottom: 0;
}
.squre {
width: 10px;
height: 4px;
background: #1890ff;
display: inline-block;
margin: 8px 8px 0 0;
}
.text {
p {
line-height: 20px;
&:nth-child(1) {
font-size: 14px;
font-weight: 600;
color: #303133;
margin-bottom: 5px;
font-family: PingFangSC-Medium, PingFang SC;
}
&:nth-child(2) {
font-size: 13px;
font-weight: 400;
color: #606266;
font-family: PingFangSC-Regular, PingFang SC;
}
}
}
}
}
}
</style>
<template>
<div class="funnel_wrap" v-if="data.length">
<div :id="nodeName"></div>
<div class="funnelDesc">
<p>
<span>{{ data[0].action }}</span>
<span class="num">{{ data[0].value }}</span>
</p>
<p>
<span class="per">{{ data[1].action }}</span>
<span class="num">{{ data[1].value }}</span>
<span class="rate">
<span>/</span>
<span>{{ data[1].rateAction }}</span>
<span class="rateNum">{{ data[1].rate }}</span>
</span>
</p>
<p>
<span class="per">{{ data[2].action }}</span>
<span class="num">{{ data[2].value }}</span>
<span class="rate">
<span>/</span>
<span>{{ data[2].rateAction }}</span>
<span class="rateNum">{{ data[2].rate }}</span>
</span>
</p>
</div>
</div>
</template>
<script>
import * as G2 from '@antv/g2';
export default {
name: 'funnel',
props: {
nodeName: String,
colorArr: Array,
data: {
type: Array
}
},
mounted() {
this.funnel();
},
methods: {
funnel() {
var chart = new G2.Chart({
container: this.nodeName,
forceFit: true,
height: 144,
padding: [0, 0, 0]
});
chart.source(this.data);
chart.axis(false);
chart.legend(false);
chart.tooltip({
showTitle: false,
itemTpl: '<li data-index={index} style="display:flex;">' + '<span style="background-color:{color};margin-top:8px;" class="g2-tooltip-marker"></span>' + '<div><p>{name} {value}</p><p>{rateAction} {rate}</p></div>' + '</li>'
});
chart
.coord('rect')
.transpose()
.scale(1, -1);
chart
.intervalSymmetric()
.position('action*value')
.shape('funnel')
.color('action', this.colorArr)
.tooltip('action*value*rate*rateAction', function(action, value, rate, rateAction) {
return {
name: action,
rate: rate,
value: value,
rateAction: rateAction
};
});
chart.render();
}
}
};
</script>
<style scoped lang="scss">
.funnel_wrap {
display: flex;
#funnel1,
#funnel2,
#funnel3 {
width: 219px;
height: 144px;
}
.funnelDesc {
padding: 14px 0 13px 10px;
p {
display: flex;
align-items: center;
height: 20px;
line-height: 20px;
&:nth-child(1) {
// margin: 0 0 23px 15px;
margin-bottom: 23px;
// margin-left: 15px;
}
&:nth-child(2) {
// margin: 0 0 33px -14px;
margin-bottom: 33px;
// margin-left: -14px;
}
&:nth-child(3) {
// margin: 0 0 0 -44px;
}
}
span {
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #303133;
white-space: nowrap;
}
.rate {
height: 22px;
display: inline-block;
display: flex;
justify-content: space-between;
span:nth-child(2) {
margin: 0 8px;
}
}
.num {
font-size: 18px;
font-family: DINAlternate-Bold, DINAlternate;
font-weight: bold;
color: #303133;
line-height: 21px;
margin: 0 8px 0 15px;
}
.rateNum {
font-size: 18px;
font-family: DINAlternate-Bold, DINAlternate;
font-weight: bold;
}
}
}
</style>
<template>
<div class="content">
<div class="top" v-if="!isCluePage">
<div class="left">计划:踏青特惠</div>
<div class="right" v-if="isRepeat">批次合计:3 / 最新批次时间:2021-03-25:12:22:33</div>
</div>
<div class="middle" v-for="(item, index) in data" :key="index">
<template v-if="item.isSales == 0">
<div class="left" v-if="isReference && !isCluePage">
<i class="iconfont icon"></i>
<span class="title">实验组</span>
<span>-计划触达</span>
</div>
</template>
<template v-else>
<div class="left" v-if="isReference && !isCluePage">
<i class="iconfont icon"></i>
<span class="title">参照组</span>
<span>-计划非触达</span>
</div>
</template>
<!--非线索页列表-->
<div class="right" :class="[isCluePage ? 'cluePage' : '']">
<div v-if="!isCluePage">
<p>计划人次</p>
<p>{{ item.planMbrTimes.toLocaleString() }}</p>
</div>
<div>
<p>{{ isCluePage ? '计划触达人数' : '计划人数' }}</p>
<p>{{ item.planMbrNum.toLocaleString() }}</p>
</div>
<div v-if="isCluePage && item.flag">
<p>
任务完成率<span>(任务总数 {{ item.taskCnt.toLocaleString() }})</span>
</p>
<p>{{ item.taskRate ? item.taskRate.toFixed(2) + '%' : '-' }}</p>
</div>
<div>
<p>
触达人数<span>(触达率 {{ item.touchRate + '%' }})</span>
</p>
<p>{{ item.touchMbrNum.toLocaleString() }}</p>
</div>
<div>
<p>
转化人数<span :class="{ active: item.isSales == 0 && data[0].transformRate < data[1].transformRate }">(转化率 {{ item.transformRate + '%' }})</span>
</p>
<p>{{ item.convMbrNum.toLocaleString() }}</p>
</div>
<div>
<p>转化订单数</p>
<p>{{ item.convOrderCnt.toLocaleString() }}</p>
</div>
<div>
<p>转化收益</p>
<p>{{ item.convSalesAmt.toLocaleString() }}</p>
</div>
</div>
<!--线索页的列表-->
<!-- <div class="right" v-else :class="[isCluePage ? 'cluePage' : '']">
<div>
<p>计划触达人次</p>
<p>{{ item.touchMbrNum.toLocaleString() }}</p>
</div>
<div>
<p>任务完成率</p>
<p>{{ item.taskRate ? item.taskRate.toFixed(2) + '%' : '-' }}</p>
</div>
<div>
<p>
触达人数<span>(触达率 {{ item.touchRate + '%' }})</span>
</p>
<p>{{ item.touchMbrNum.toLocaleString() }}</p>
</div>
<div>
<p>
转化人数
</p>
<p>{{ item.convMbrNum.toLocaleString() }}</p>
</div>
<div>
<p>转化订单数</p>
<p>{{ item.convOrderCnt.toLocaleString() }}</p>
</div>
<div>
<p>转化收益</p>
<p>{{ item.convSalesAmt.toLocaleString() }}</p>
</div>
</div> -->
</div>
</div>
</template>
<script>
export default {
name: 'market-list',
props: {
// 是否是线索页面
isCluePage: {
type: Boolean,
default: false
},
// 是否重复营销
isRepeat: {
type: Boolean,
default: true
},
// 是否勾选参照组
isReference: {
type: Boolean,
default: true
},
// 数据
data: {
type: Array,
default: () => []
}
}
};
</script>
<style lang="scss" scoped>
.content {
font-family: PingFangSC-Medium, PingFang SC;
margin-left: 8px;
margin-right: 13px;
.top {
color: #303133;
height: 50px;
background: #f5f7fa;
border-radius: 6px;
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 5px;
margin-top: 10px;
.left {
font-size: 16px;
font-weight: 600;
line-height: 22px;
padding-left: 27px;
}
.right {
font-family: PingFangSC-Regular, PingFang SC;
font-size: 14px;
font-weight: 400;
line-height: 20px;
padding-right: 16px;
}
}
.middle {
margin-bottom: 4px;
height: 100px;
background: #f0f5ff;
border-radius: 6px;
display: flex;
align-items: center;
.left {
width: 226px;
height: 55px;
box-sizing: border-box;
display: flex;
align-items: center;
padding: 0 35px 0 25px;
border-right: 1px solid#E4E7ED;
span {
font-size: 14px;
font-weight: 400;
color: #606266;
line-height: 20px;
}
.title {
font-weight: 600;
color: #303133;
margin-right: 4px;
}
.icon {
width: 40px;
height: 40px;
background: rgba(144, 188, 255, 0.21);
border-radius: 4px;
margin-right: 15px;
}
}
.right {
padding: 0 28px 0 32px;
height: 58px;
flex: 1;
display: flex;
justify-content: space-between;
div {
p {
&:nth-child(1) {
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #606266;
line-height: 20px;
padding-top: 4px;
margin-bottom: 6px;
}
&:nth-child(2) {
font-size: 24px;
font-family: DINAlternate-Bold, DINAlternate;
font-weight: bold;
color: #303133;
line-height: 28px;
}
.active {
color: #f5222d;
margin-left: 4px;
}
}
}
}
.cluePage {
padding-left: 65px;
}
&:nth-of-type(3) {
background: #f5f7fa;
margin-bottom: 7px;
.left {
padding-right: 21px;
}
}
}
}
</style>
<template>
<div class="draw">
<div id="draw_g2"></div>
</div>
</template>
<script>
import * as G2 from '@antv/g2';
export default {
name: 'touch-charts',
props: {
data: {
type: Array,
default: () => []
}
},
mounted() {
this.draw();
},
methods: {
draw() {
const chart = new G2.Chart({
container: 'draw_g2',
forceFit: true,
height: 376,
padding: [55, 90, 46, 68]
});
chart.source(this.data);
chart.tooltip({
showMarkers: false,
shared: true
});
chart.legend({
position: 'top',
offsetY: -20
});
chart.axis('value', {
grid: {
type: 'line',
lineStyle: {
stroke: '#d9d9d9',
lineWidth: 1,
lineDash: [-1, -1]
}
}
});
chart.scale({
date: {
dataKey: 'date',
type: 'cat'
},
value: {
min: 0,
tickCount: 5
},
rate: {
min: 0,
tickCount: 5
}
});
chart.axis('rate', {
label: {
formatter: text => {
let num = Number(text);
if (num > 10000) {
return num / 10000 + '万';
}
return num + '元';
}
},
grid: null
});
chart
.interval()
.position('date*value')
.color('name', ['rgba(91, 143, 249, 0.85)', 'rgba(90, 216, 166, 0.85)', '#FF9F40'])
.adjust([
{
type: 'dodge',
marginRatio: 0.1
}
]); // eslint-disable-next-line
chart
.line()
.position('date*rate')
.color('name', ['#FF9F40']);
chart.render();
}
}
};
</script>
<style lang="scss" scoped>
.draw {
.title {
padding-left: 12px;
font-size: 16px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 700;
color: #303133;
line-height: 22px;
margin-bottom: 36px;
}
#draw_g2 {
height: 376px;
margin: 0 auto;
position: relative;
font-size: 12px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: rgba(0, 0, 0, 0.45);
line-height: 17px;
&::before {
content: '人数';
position: absolute;
top: 10px;
left: 41px;
}
&::after {
content: '金额';
position: absolute;
top: 10px;
right: 57px;
}
}
}
</style>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment