Commit eed1395e by 黑潮

Merge branch 'feature/销售线索2期' of http://115.159.76.241/marketing-web/marketing into feature/销售线索2期

parents 916004df 3e636d9e
......@@ -64,7 +64,7 @@ export default {
return this.$store.state.marketing.layoutTips;
},
showDescription() {
return (this.$route.path.indexOf('ecm/list') >= 0 || this.$route.path.indexOf('ecm/clue') >= 0 || this.$route.path.indexOf('ecm/touch') >= 0) && this.$store.state.marketing.xsxsFlag;
return (this.$route.path.indexOf('ecm/list') >= 0 && this.$store.state.marketing.xsxsFlag) || this.$route.path.indexOf('ecm/clue') >= 0 || this.$route.path.indexOf('ecm/touch') >= 0;
}
},
// watch:{
......
......@@ -198,6 +198,17 @@ export default {
if (!openFlag) openFlag = {};
return openFlag.open_flag == 0 || (!row.ecmTranIncome && row.ecmTranIncome != 0) ? '--' : row.ecmTranIncome.toFixed(2);
}
},
{
label: '卡券收益', // 字段名需要更改------------------------------------------------
prop: 'ecmTranIncome',
minWidth: '120',
align: 'left',
formatter(row) {
let openFlag = JSON.parse(row.analyseJson);
if (!openFlag) openFlag = {};
return openFlag.open_flag == 0 || (!row.ecmTranIncome && row.ecmTranIncome != 0) ? '--' : row.ecmTranIncome.toFixed(2);
}
}
],
tableList: []
......
......@@ -205,13 +205,24 @@ export default {
return `<span style="background:${color};color:${textColor};width: 16px; display: inline-block; text-align: center; line-height:16px">${row.index}</span>`;
}
},
{ label: '门店名称', prop: 'storeName', minWidth: '160', align: 'left', fixed: 'left' },
{ label: '触达人数', prop: 'touchMbrNum', minWidth: '160', align: 'left', fixed: 'left', sortable: 'custom' },
{ label: '触达率', prop: 'reachRate', minWidth: '160', align: 'left', fixed: 'left', sortable: 'custom', formatter: row => row.reachRate && row.reachRate.toFixed(2) + '%' },
{ label: '转化人数', prop: 'convMbrNum', minWidth: '160', align: 'left', fixed: 'left', sortable: 'custom' },
{ label: '触达转化收益', prop: 'convSalesAmt', minWidth: '160', align: 'left', fixed: 'left', sortable: 'custom', formatter: row => row.convSalesAmt && row.convSalesAmt.toFixed(2) },
{ label: '客单价', prop: 'customerPrice', minWidth: '160', align: 'left', fixed: 'left', sortable: 'custom', formatter: row => row.customerPrice && row.customerPrice.toFixed(2) },
{ label: '折扣率', prop: 'discountRate', minWidth: '160', align: 'left', fixed: 'left', sortable: 'custom', formatter: row => row.discountRate && row.discountRate.toFixed(2) }
{
label: '门店名称',
prop: 'storeName',
minWidth: '160',
align: 'left',
fixed: 'left',
formatter(row) {
if (!row.storeName) return '--';
else if (row.storeName == '-1') return '【无归属门店】';
return row.storeName;
}
},
{ label: '触达人数', prop: 'touchMbrNum', minWidth: '160', align: 'left', fixed: 'left', sortable: 'custom', formatter: row => this.formatterNum(row.touchMbrNum) },
{ label: '触达率', prop: 'reachRate', minWidth: '160', align: 'left', fixed: 'left', sortable: 'custom', formatter: row => this.formatterRate(row.reachRate) },
{ label: '转化人数', prop: 'convMbrNum', minWidth: '160', align: 'left', fixed: 'left', sortable: 'custom', formatter: row => this.formatterNum(row.convMbrNum) },
{ label: '触达转化收益', prop: 'convSalesAmt', minWidth: '160', align: 'left', fixed: 'left', sortable: 'custom', formatter: row => this.formatterToFixed(row.convSalesAmt) },
{ label: '客单价', prop: 'customerPrice', minWidth: '160', align: 'left', fixed: 'left', sortable: 'custom', formatter: row => this.formatterToFixed(row.customerPrice) },
{ label: '折扣率', prop: 'discountRate', minWidth: '160', align: 'left', fixed: 'left', sortable: 'custom', formatter: row => this.formatterToFixed(row.discountRate) }
];
}
if (this.type == 1 && this.listTabsIndex == 0) {
......@@ -236,13 +247,24 @@ export default {
return `<span style="background:${color};width: 16px; display: inline-block; text-align: center; line-height:16px">${row.index}</span>`;
}
},
{ label: '门店名称', prop: 'storeName', minWidth: '160', align: 'left', fixed: 'left' },
{ label: '任务总数', prop: 'taskCnt', minWidth: '160', align: 'left', fixed: 'left', sortable: 'custom' },
{ label: '任务完成数', prop: 'cplTaskCnt', minWidth: '160', align: 'left', fixed: 'left', sortable: 'custom' },
{ label: '任务完成率', prop: 'taskCompletionRate', minWidth: '160', align: 'left', fixed: 'left', sortable: 'custom', formatter: row => row.taskCompletionRate && row.taskCompletionRate.toFixed(2) + '%' },
{ label: '任务放弃数', prop: 'tasksAbandonedNum', minWidth: '160', align: 'left', fixed: 'left', sortable: 'custom' },
{ label: '逾期未完成', prop: 'overdueNotCompleted', minWidth: '160', align: 'left', fixed: 'left', sortable: 'custom' },
{ label: '未完成', prop: 'notCompleted', minWidth: '160', align: 'left', fixed: 'left', sortable: 'custom' }
{
label: '门店名称',
prop: 'storeName',
minWidth: '160',
align: 'left',
fixed: 'left',
formatter(row) {
if (!row.storeName) return '--';
else if (row.storeName == '-1') return '【无归属门店】';
return row.storeName;
}
},
{ label: '任务总数', prop: 'taskCnt', minWidth: '160', align: 'left', fixed: 'left', sortable: 'custom', formatter: row => this.formatterNum(row.taskCnt) },
{ label: '任务完成数', prop: 'cplTaskCnt', minWidth: '160', align: 'left', fixed: 'left', sortable: 'custom', formatter: row => this.formatterNum(row.cplTaskCnt) },
{ label: '任务完成率', prop: 'taskCompletionRate', minWidth: '160', align: 'left', fixed: 'left', sortable: 'custom', formatter: row => this.formatterRate(row.taskCompletionRate) },
{ label: '任务放弃数', prop: 'tasksAbandonedNum', minWidth: '160', align: 'left', fixed: 'left', sortable: 'custom', formatter: row => this.formatterNum(row.tasksAbandonedNum) },
{ label: '逾期未完成', prop: 'overdueNotCompleted', minWidth: '160', align: 'left', fixed: 'left', sortable: 'custom', formatter: row => this.formatterNum(row.overdueNotCompleted) },
{ label: '未完成', prop: 'notCompleted', minWidth: '160', align: 'left', fixed: 'left', sortable: 'custom', formatter: row => this.formatterNum(row.notCompleted) }
];
}
},
......@@ -371,6 +393,21 @@ export default {
'text-align': 'center',
'line-height': '16px'
};
},
formatterNum() {
return val => {
return !val && val != 0 ? '--' : parseInt(val).toLocaleString();
};
},
formatterToFixed() {
return val => {
return !val && val != 0 ? '--' : parseFloat(val).toFixed(2);
};
},
formatterRate() {
return val => {
return !val && val != 0 ? '--' : parseFloat(val).toFixed(2) + '%';
};
}
},
watch: {
......
<template>
<div class="dm-wrap card_profit">
<div class="title">
<h2>卡券收益</h2>
<span>计划中的卡券,计划中卡券触达的人群使用该卡券消费的收益,包含已过计划收益有效期的数据</span>
</div>
<template v-if="isCardProfit">
<div class="list">
<div class="list_left">
<div>
<p>触达人数</p>
<p>80,120</p>
</div>
<div>
<p>领取人数<span> (领取率 71.25%)</span></p>
<p>80,102</p>
</div>
<div>
<p>使用人数<span> (使用率 71.25%)</span></p>
<p>80,332</p>
</div>
</div>
<div class="list_right">
<div>
<p>销售单数</p>
<p>80,120</p>
</div>
<div>
<p>销售单金额(元)</p>
<p>80,102</p>
</div>
<div>
<p>退货/换货金额(元)</p>
<p>10,302,300</p>
</div>
</div>
</div>
<el-table :data="tableData" v-if="tableData.length" style="margin-bottom:47px" max-height="710">
<el-table-column :prop="name" label="卡券名称" min-width="100">
<template slot-scope="scope">
<div class="name" v-if="scope.row.name">
<div class="top">
{{ scope.row.name }}
<span class="type">折扣券</span>
</div>
<p>卡券副标题</p>
</div>
</template>
</el-table-column>
<el-table-column v-for="(v, i) in tableHeader" :key="i" :prop="v.prop" :label="v.label" :formatter="v.formatter">
<template slot-scope="scope">
<span v-if="v.formatter" v-html="v.formatter(scope.row)"></span>
<span v-else>{{ scope.row[v.prop] }}</span>
</template>
</el-table-column>
</el-table>
</template>
<div class="empty" v-else>
<div class="content">
<span class="icon iconfont">&#xe76e;</span>
<span>本计划未使用卡券营销</span>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'card-profit',
data() {
return {
isCardProfit: true, // 是否使用卡券营销
tableData: [
{
name: 'XXX生日8折券',
touchNum: null,
drawNum: null,
drawRate: null,
useNum: null,
useRate: null,
salesNum: null,
salesMoney: null,
refundMoney: null
}
],
tableHeader: [
{ label: '触达人数', prop: 'touchNum', minWidth: '160', align: 'left', fixed: 'left', formatter: row => this.formatterNum(row.touchNum) },
{ label: '领取人数', prop: 'drawNum', minWidth: '160', align: 'left', fixed: 'left', formatter: row => this.formatterNum(row.drawNum) },
{ label: '领取率', prop: 'drawRate', minWidth: '160', align: 'left', fixed: 'left', formatter: row => this.formatterRate(row.drawRate) },
{ label: '使用人数', prop: 'useNum', minWidth: '160', align: 'left', fixed: 'left', formatter: row => this.formatterNum(row.useNum) },
{ label: '使用率', prop: 'useRate', minWidth: '160', align: 'left', fixed: 'left', formatter: row => this.formatterRate(row.useRate) },
{ label: '销售单数', prop: 'salesNum', minWidth: '160', align: 'left', fixed: 'left', formatter: row => this.formatterNum(row.salesNum) },
{ label: '销售单金额', prop: 'salesMoney', minWidth: '160', align: 'left', fixed: 'left', formatter: row => this.formatterNum(row.salesMoney) },
{ label: '退货/换货金额', prop: 'refundMoney', minWidth: '160', align: 'left', fixed: 'left', formatter: row => this.formatterNum(row.refundMoney) }
]
};
},
computed: {
formatterNum() {
return val => {
return !val && val != 0 ? '--' : parseInt(val).toLocaleString();
};
},
formatterRate() {
return val => {
return !val && val != 0 ? '--' : parseFloat(val).toFixed(2) + '%';
};
}
}
};
</script>
<style scoped lang="scss">
.card_profit {
padding: 19px 34px 7px 28px !important;
margin-bottom: 10px !important;
font-family: PingFangSC-Regular, PingFang SC;
.title {
padding-left: 4px;
margin-bottom: 20px;
display: flex;
align-items: center;
h2 {
font-size: 16px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 700;
color: #303133;
line-height: 22px;
}
span {
margin-left: 28px;
font-size: 14px;
color: #909399;
}
}
.list {
display: flex;
justify-content: space-between;
margin-bottom: 20px;
.list_left {
margin-right: 10px;
}
.list_left,
.list_right {
background: #f0f5ff;
border-radius: 6px;
flex: 1;
height: 115px;
padding-left: 40px;
box-sizing: border-box;
display: flex;
div {
flex: 1;
padding-top: 26px;
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;
}
span {
color: #303133;
}
}
}
}
}
.name {
color: #303133;
line-height: 22px;
.top {
display: flex;
align-items: center;
.type {
display: inline-block;
width: 42px;
height: 16px;
line-height: 18px;
text-align: center;
background: #fff1f0;
border-radius: 2px;
border: 1px solid #ffa39e;
font-size: 12px;
color: #f5222d;
margin-left: 4px;
}
}
p {
font-size: 12px;
color: #909399;
line-height: 22px;
}
}
.empty {
display: flex;
align-items: center;
justify-content: center;
height: 200px;
color: #909399;
font-size: 16px;
.content {
display: flex;
align-items: center;
.icon {
font-size: 30px;
margin-right: 10px;
}
}
}
}
</style>
<template>
<!--文字说明-->
<el-drawer title="触达效果说明" :visible.sync="drawer" :direction="direction" custom-class="touch_drawer h670" v-if="contentTitle == '触达效果'">
<el-drawer title="触达效果说明" :visible.sync="drawer" :direction="direction" custom-class="touch_drawer h790" v-if="contentTitle == '触达效果'">
<ul class="content">
<li>数据更新频率:1天1次</li>
<li>
......@@ -38,6 +38,16 @@
</p>
</div>
</li>
<li>
<span class="squre"></span>
<div class="text">
<p>5. 卡券收益</p>
<p>
① 计划中的卡券,计划中卡券触达的人群使用该卡券消费的收益,包含已过计划收益有效期的数据。<br />
② 一个计划中使用多张卡券的,计划粒度上卡券收益去重,各卡券数据相加可能不等于整体数据。
</p>
</div>
</li>
</ul>
</el-drawer>
<el-drawer title="【导购线索】说明" :visible.sync="drawer" :direction="direction" custom-class="touch_drawer h850" v-else-if="contentTitle == '导购线索'">
......@@ -132,16 +142,17 @@
</li>
</ul>
</el-drawer>
<el-drawer title="数据说明" :visible.sync="drawer" :direction="direction" custom-class="touch_drawer h380" v-else-if="contentTitle == '智能营销'">
<el-drawer title="数据说明" :visible.sync="drawer" :direction="direction" custom-class="touch_drawer h440" v-else-if="contentTitle == '智能营销'">
<ul class="content">
<li>更新频率:营销人次实时统计,其余指标1天更新1次;</li>
<li>
①【营销人次】:本智能营销计划预计营销的人次;<br />
②【计划触达人数】:本计划计划触达的人数。一些预计营销的人中因为一些系统特殊情况导致触发失败的,不会计入在内;重复营销的,只记1人<br />
②【计划触达人数】:本计划计划触达的人数。一些预计营销的人中因为一些系统特殊情况导致触发失败的,不会计入在内;重复营销的,只记1人<br />
③【触达人数】:通过计划中各种营销方式触达到的会员人数;<br />
④【转化人数】:触达的人中,在触达收益有效期内前来消费的人数;<br />
⑤【线索转化收益】:转化人数带来的收益,只计销售单,不看退货单和换货单;金额是应付还是实付看ERP传入的值。<br />
⑥ 说明:未开启营销分析开关的,除营销人次外其他指标信息不统计;
⑤【线索转化收益】:转化人数带来的收益,只计销售单,不看退货单和换货单;金额是应付还是实付看ERP传入的值;<br />
⑥【卡券收益】:计划中的卡券,计划中卡券触达的人群使用该卡券消费的收益,包含已过计划收益有效期的数据;<br />
⑦ 说明:未开启营销分析开关的,除营销人次外其他指标信息不统计;
</li>
</ul>
</el-drawer>
......@@ -172,11 +183,14 @@ export default {
.h850 {
height: 850px !important;
}
.h790 {
height: 790px !important;
}
.h670 {
height: 670px !important;
}
.h380 {
height: 380px !important;
.h440 {
height: 440px !important;
}
.touch_drawer {
width: 395px !important;
......
<template>
<div class="touch" v-loading="loading">
<div class="dm-wrap">
<div class="dm-wrap effect">
<div class="title">
<h2>触达效果</h2>
</div>
<touch-charts :type="0" />
<market-list v-if="marketListData.length" :isRepeat="isRepeat" :data="marketListData" :isReference="isReference" :batchNum="batchNum" :batchTimes="batchTime" />
</div>
<div class="dm-wrap table">
<cardType />
<div class="dm-wrap effect table">
<div class="title">
<span>线索转化对比</span>
</div>
......@@ -68,6 +69,7 @@
import funnel from '@/views/ecm/touch-components/funnel.vue';
import marketList from '@/views/ecm/touch-components/market-list.vue';
import touchCharts from '@/views/ecm/touch-components/touch-charts.vue';
import cardType from '@/views/ecm/touch-components/card-profit.vue';
import { ecmTouchEffectTable, ecmTouchEffectFunnelChart, ecmPlanTouchConfig } from '@/service/api/ecmApi.js';
// ecmPlanTouchConfig
export default {
......@@ -88,7 +90,8 @@ export default {
components: {
marketList,
touchCharts,
funnel
funnel,
cardType
},
mounted() {
this.ecmPlanId = this.$route.params.id;
......@@ -204,7 +207,7 @@ export default {
};
</script>
<style lang="scss" scoped>
.dm-wrap {
.effect {
padding: 16px 20px 27px !important;
margin-bottom: 10px !important;
.title {
......
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