Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
M
marketing
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
marketing-web
marketing
Commits
7878e30d
Commit
7878e30d
authored
Apr 24, 2021
by
liuchenxi
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
-触达效果-
parent
3a8594d6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
56 additions
and
40 deletions
+56
-40
touch-clue.vue
src/views/ecm/touch-clue.vue
+24
-16
description.vue
src/views/ecm/touch-components/description.vue
+4
-1
funnel.vue
src/views/ecm/touch-components/funnel.vue
+2
-1
market-list.vue
src/views/ecm/touch-components/market-list.vue
+12
-10
touch-charts.vue
src/views/ecm/touch-components/touch-charts.vue
+1
-1
touch-effect.vue
src/views/ecm/touch-effect.vue
+13
-11
No files found.
src/views/ecm/touch-clue.vue
View file @
7878e30d
...
...
@@ -17,7 +17,7 @@
<span
v-for=
"item in listTabsIndex == 1 ? touchTabs : taskTabs"
:key=
"item.value"
:class=
"
{ active2: listTabsIndex == 1 ? item.value == tabsIndex : item.value == taskTabIndex }" @click="changeTabs(item.value)">
{{
item
.
name
}}
</span>
</div>
</div>
<el-table
tooltipEffect=
"light"
:data=
"tableList"
style=
"width: 100%"
element-loading-text=
"拼命加载中"
@
sort-change=
"sortChange"
:style=
"
{ marginTop: '20px', padding: '0 20px 0 22px' }">
<el-table
ref=
"table"
tooltipEffect=
"light"
:data=
"tableList"
style=
"width: 100%"
element-loading-text=
"拼命加载中"
@
sort-change=
"sortChange"
:style=
"
{ marginTop: '20px', padding: '0 20px 0 22px' }">
<el-table-column
v-for=
"(v, i) in tableHeader"
:key=
"i"
:prop=
"v.prop"
:label=
"v.label"
:formatter=
"v.formatter"
:sortable=
"v.sortable"
>
<template
slot-scope=
"scope"
>
<span
v-if=
"v.formatter"
v-html=
"v.formatter(scope.row)"
></span>
...
...
@@ -32,7 +32,6 @@
<
script
>
import
{
ecmGuideCluesTable
,
ecmHeadCluesTaskTab
,
ecmHeadGuideCluesTable
,
ecmHeadCluesTaskTabHead
,
ecmGuideCluesTaskTable
,
ecmGuideCluesTouchEffectTotalTab
,
ecmGuideCluesTouchEffectTabTotalHead
,
ecmGuideCluesTouchEffectTab
,
ecmGuideCluesTouchEffectTabHead
}
from
'@/service/api/ecmApi.js'
;
// import { ecmGuideCluesTable, ecmHeadCluesTaskTab, ecmHeadGuideCluesTable, ecmHeadCluesTaskTabHead, ecmGuideCluesTaskTable, ecmGuideCluesTouchEffectTotalTab } from '@/service/api/ecmApi.js';ecmGuideCluesTouchEffectTab
import
marketList
from
'@/views/ecm/touch-components/market-list.vue'
;
import
touchCharts
from
'@/views/ecm/touch-components/touch-charts.vue'
;
export
default
{
...
...
@@ -91,7 +90,8 @@ export default {
pageSize
:
20
,
total
:
0
,
tableFirstData
:
{},
ordery
:
''
touchOrderBy
:
''
,
taskOrderBy
:
''
};
},
mounted
()
{
...
...
@@ -118,15 +118,19 @@ export default {
changeTabs
(
index
)
{
if
(
this
.
listTabsIndex
==
1
)
{
if
(
this
.
tabsIndex
==
index
)
return
;
this
.
touchOrderBy
=
''
;
this
.
tabsIndex
=
index
;
}
else
{
if
(
this
.
taskTabIndex
==
index
)
return
;
this
.
taskOrderBy
=
''
;
this
.
taskTabIndex
=
index
;
}
this
.
$refs
.
table
.
clearSort
();
this
.
getTableFirstData
();
},
changeListTab
(
index
)
{
this
.
listTabsIndex
=
index
;
this
.
$refs
.
table
.
clearSort
();
this
.
getTableList
();
},
getMarketList
()
{
...
...
@@ -140,8 +144,8 @@ export default {
data
.
taskRate
=
(
data
.
cplTaskTotalCnt
/
data
.
taskCnt
)
*
100
;
data
.
flag
=
true
;
}
data
.
touchRate
=
data
?
parseFloat
(((
data
.
touchMbrNum
/
data
.
planMbrNum
)
*
100
).
toFixed
(
2
))
:
0
;
data
.
transformRate
=
data
?
parseFloat
(((
data
.
convMbrNum
/
data
.
touchMbrNum
)
*
100
).
toFixed
(
2
))
:
0
;
data
.
touchRate
=
parseFloat
(((
data
.
touchMbrNum
/
data
.
planMbrNum
)
*
100
).
toFixed
(
2
))
;
data
.
transformRate
=
parseFloat
(((
data
.
convMbrNum
/
data
.
touchMbrNum
)
*
100
).
toFixed
(
2
))
;
this
.
marketListData
=
[{
...
data
}];
});
},
...
...
@@ -156,7 +160,6 @@ export default {
fixed
:
'left'
,
formatter
(
row
)
{
let
color
=
'#F0F5FF'
;
if
(
!
row
)
return
;
if
(
row
.
index
==
1
)
{
color
=
'#F5222D'
;
}
else
if
(
row
.
index
==
2
)
{
...
...
@@ -171,11 +174,11 @@ export default {
},
{
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'
},
{
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'
},
{
label
:
'客单价'
,
prop
:
'customerPrice'
,
minWidth
:
'160'
,
align
:
'left'
,
fixed
:
'left'
,
sortable
:
'custom'
},
{
label
:
'折扣率'
,
prop
:
'discountRate'
,
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
)
}
];
}
if
(
this
.
type
==
1
&&
this
.
listTabsIndex
==
0
)
{
...
...
@@ -187,7 +190,6 @@ export default {
align
:
'left'
,
fixed
:
'left'
,
formatter
(
row
)
{
if
(
!
row
)
return
;
let
color
=
'#F0F5FF'
;
if
(
row
.
index
==
1
)
{
color
=
'#F5222D'
;
...
...
@@ -204,7 +206,7 @@ export default {
{
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'
},
{
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'
}
...
...
@@ -213,7 +215,7 @@ export default {
},
getTableList
()
{
let
meth
;
let
params
=
{
ecmPlanId
:
this
.
$route
.
query
.
id
,
pageNum
:
this
.
currentPage
,
pageSize
:
this
.
pageSize
,
orderBy
:
this
.
orderBy
?
this
.
orderBy
:
''
};
let
params
=
{
ecmPlanId
:
this
.
$route
.
query
.
id
,
pageNum
:
this
.
currentPage
,
pageSize
:
this
.
pageSize
,
orderBy
:
this
.
listTabsIndex
==
1
?
this
.
touchOrderBy
:
this
.
taskOrderBy
};
if
(
this
.
type
==
2
)
{
// 后台线索
meth
=
ecmHeadCluesTaskTab
;
...
...
@@ -236,18 +238,19 @@ export default {
}
}
meth
(
params
).
then
(
res
=>
{
if
(
!
res
.
result
.
result
||
!
res
.
result
.
result
.
length
)
return
;
if
(
this
.
currentPage
==
1
&&
this
.
listTabsIndex
!=
0
)
{
// 任务完成情况无表头
let
resetArr
=
[];
resetArr
[
0
]
=
this
.
tableFirstData
;
res
.
result
.
result
&&
(
this
.
tableList
=
resetArr
.
concat
(
res
.
result
.
result
));
}
else
{
this
.
tableList
=
res
.
result
.
result
||
[]
;
this
.
tableList
=
res
.
result
.
result
;
}
this
.
total
=
res
.
result
.
totalCount
;
this
.
loading
=
false
;
});
this
.
tableList
.
length
&&
this
.
getTableHeader
();
this
.
getTableHeader
();
},
getTableFirstData
()
{
let
meth
;
...
...
@@ -274,11 +277,16 @@ export default {
});
},
sortChange
(
column
)
{
console
.
log
(
column
);
let
prop
=
column
.
prop
;
let
orderby
=
column
.
order
;
if
(
orderby
==
'descending'
)
orderby
=
'desc'
;
else
orderby
=
'asc'
;
this
.
orderBy
=
prop
+
' '
+
orderby
;
if
(
this
.
listTabsIndex
==
1
)
{
this
.
touchOrderBy
=
prop
+
' '
+
orderby
;
}
else
{
this
.
taskOrderBy
=
prop
+
' '
+
orderby
;
}
this
.
getTableList
();
}
},
...
...
src/views/ecm/touch-components/description.vue
View file @
7878e30d
...
...
@@ -132,7 +132,7 @@
</li>
</ul>
</el-drawer>
<el-drawer
title=
"数据说明"
:visible
.
sync=
"drawer"
:direction=
"direction"
custom-class=
"touch_drawer h
65
0"
v-else-if=
"contentTitle == '智能营销'"
>
<el-drawer
title=
"数据说明"
:visible
.
sync=
"drawer"
:direction=
"direction"
custom-class=
"touch_drawer h
38
0"
v-else-if=
"contentTitle == '智能营销'"
>
<ul
class=
"content"
>
<li>
更新频率:营销人次实时统计,其余指标1天更新1次;
</li>
<li>
...
...
@@ -178,6 +178,9 @@ export default {
.h670
{
height
:
670px
!important
;
}
.h380
{
height
:
380px
!important
;
}
.touch_drawer
{
width
:
395px
!important
;
background
:
#ffffff
;
...
...
src/views/ecm/touch-components/funnel.vue
View file @
7878e30d
...
...
@@ -36,7 +36,8 @@ export default {
nodeName
:
String
,
colorArr
:
Array
,
data
:
{
type
:
Array
type
:
Array
,
default
:
()
=>
[]
}
},
mounted
()
{
...
...
src/views/ecm/touch-components/market-list.vue
View file @
7878e30d
...
...
@@ -5,7 +5,7 @@
<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
"
>
<template
v-if=
"item.isSales ==
1
"
>
<div
class=
"left"
v-if=
"isReference && !isCluePage"
>
<img
:src=
"require('@/assets/img/experimentIcon.png')"
class=
"icon"
/>
<span
class=
"title"
>
实验组
</span>
...
...
@@ -23,33 +23,33 @@
<div
class=
"right"
:class=
"[isCluePage ? 'cluePage' : '']"
>
<div
v-if=
"!isCluePage"
>
<p>
计划人次
</p>
<p>
{{ item.planMbrTime
&&
item.planMbrTimes.toLocaleString()
}}
</p>
<p>
{{ item.planMbrTime
s ? item.planMbrTimes.toLocaleString() : 0
}}
</p>
</div>
<div>
<p>
{{ isCluePage ? '计划触达人数' : '计划人数' }}
</p>
<p>
{{ item.planMbrNum
&&
item.planMbrNum.toLocaleString()
}}
</p>
<p>
{{ item.planMbrNum
? item.planMbrNum.toLocaleString() : 0
}}
</p>
</div>
<div
v-if=
"isCluePage && item.flag"
>
<p>
任务完成率
<span>
(任务总数 {{ item.taskCnt
&&
item.taskCnt.toLocaleString()
}})
</span>
任务完成率
<span>
(任务总数 {{ item.taskCnt
? item.taskCnt.toLocaleString() : 0
}})
</span>
</p>
<p>
{{ item.taskRate ? item.taskRate.toFixed(2) + '%' :
'-'
}}
</p>
<p>
{{ item.taskRate ? item.taskRate.toFixed(2) + '%' :
0
}}
</p>
</div>
<div>
<p>
触达人数
<span>
(触达率 {{ item.touchRate + '%' }})
</span>
触达人数
<span>
(触达率 {{ item.touchRate
? item.touchRate + '%' : 0
+ '%' }})
</span>
</p>
<p>
{{ item.touchMbrNum
&&
item.touchMbrNum.toLocaleString()
}}
</p>
<p>
{{ item.touchMbrNum
? item.touchMbrNum.toLocaleString() : 0
}}
</p>
</div>
<div>
<p>
转化人数
<span
:class=
"{ active: item.isSales ==
0 && data[0].transformRate < data[1].transformRate }"
>
(转化率 {{ item.transformRate
+ '%' }})
</span>
转化人数
<span
:class=
"{ active: item.isSales ==
1 && data[0].transformRate < data[1].transformRate }"
>
(转化率 {{ item.transformRate ? item.transformRate + '%' : 0
+ '%' }})
</span>
</p>
<p>
{{ item.convMbrNum
&&
item.convMbrNum.toLocaleString()
}}
</p>
<p>
{{ item.convMbrNum
? item.convMbrNum.toLocaleString() : 0
}}
</p>
</div>
<div>
<p>
转化订单数
</p>
<p>
{{ item.convOrderCnt
&&
item.convOrderCnt.toLocaleString()
}}
</p>
<p>
{{ item.convOrderCnt
? item.convOrderCnt.toLocaleString() : 0
}}
</p>
</div>
<div>
<p>
转化收益
</p>
...
...
@@ -87,6 +87,7 @@ export default {
},
computed
:
{
convSalesAmt
(
num
)
{
console
.
log
(
this
.
data
);
return
num
=>
{
if
(
num
)
{
num
=
parseFloat
(
num
).
toFixed
(
2
);
...
...
@@ -151,6 +152,7 @@ export default {
font-weight
:
400
;
color
:
#606266
;
line-height
:
20px
;
white-space
:
nowrap
;
}
.title
{
font-weight
:
600
;
...
...
src/views/ecm/touch-components/touch-charts.vue
View file @
7878e30d
...
...
@@ -99,7 +99,7 @@ export default {
if
(
this
.
type
==
0
)
meth
=
ecmTouchEffectColumnDiagram
;
else
if
(
this
.
type
==
1
)
meth
=
ecmGuideCluesColumnDiagram
;
else
meth
=
ecmHeadCluesColumnDiagram
;
meth
({
ecmPlanId
:
this
.
$route
.
query
.
id
}).
then
(
res
=>
{
meth
({
ecmPlanId
:
this
.
$route
.
query
.
id
||
this
.
$route
.
params
.
id
}).
then
(
res
=>
{
this
.
chartData
=
res
.
result
.
map
(
item
=>
{
if
(
item
.
name
==
'线索转化收益'
)
{
item
.
rate
=
item
.
vaule
*
1
;
...
...
src/views/ecm/touch-effect.vue
View file @
7878e30d
...
...
@@ -31,7 +31,7 @@
<div
class=
"detail"
@
click=
"toClue(1)"
>
查看详情
</div>
<div
class=
"allPlan_title"
>
导购线索
</div>
<div
class=
"allPlan_content"
>
<div
class=
"left"
>
<div
class=
"
allPlan_content_
left"
>
<img
:src=
"require('@/assets/img/funnelIcon1.png')"
class=
"icon"
/>
<div>
<p>
线索转化收益
</p>
...
...
@@ -47,7 +47,7 @@
<div
class=
"detail"
@
click=
"toClue(2)"
>
查看详情
</div>
<div
class=
"allPlan_title"
>
后台线索
</div>
<div
class=
"allPlan_content"
>
<div
class=
"left"
>
<div
class=
"
allPlan_content_
left"
>
<img
:src=
"require('@/assets/img/funnelIcon2.png')"
class=
"icon"
/>
<div>
<p>
线索转化收益
</p>
...
...
@@ -113,7 +113,7 @@ export default {
ecmTouchEffectFunnelChart
({
ecmPlanId
:
this
.
ecmPlanId
}).
then
(
res
=>
{
this
.
funnelData
=
this
.
formatFunnelData
(
res
.
result
);
this
.
clueRate
=
res
.
result
.
map
(
item
=>
{
if
(
item
.
线索转化收益
)
{
if
(
item
.
线索转化收益
&&
parseFloat
(
item
.
线索转化收益
)
)
{
item
=
parseFloat
(
item
.
线索转化收益
).
toFixed
(
2
);
let
i
=
item
.
indexOf
(
'.'
);
let
before
=
parseInt
(
item
.
slice
(
0
,
i
)).
toLocaleString
();
...
...
@@ -133,22 +133,22 @@ export default {
if
(
i
!=
'收益'
&&
i
==
'触达人数'
&&
item
[
i
]
&&
item
.
计划触达人数
)
{
obj
.
unshift
({
action
:
i
,
value
:
item
[
i
]
*
1
,
value
:
parseInt
(
item
[
i
])
?
item
[
i
]
*
1
:
0
,
rateAction
:
'触达率'
,
rate
:
(
(
item
.
触达人数
/
item
.
计划触达人数
)
*
100
).
toFixed
(
2
)
+
'%'
rate
:
(
item
.
触达人数
/
item
.
计划触达人数
)
*
100
?
((
item
.
触达人数
/
item
.
计划触达人数
)
*
100
).
toFixed
(
2
)
+
'%'
:
0
+
'%'
});
}
else
if
(
i
!=
'收益'
&&
i
==
'转化人数'
&&
item
[
i
]
&&
item
.
计划触达人数
)
{
obj
.
unshift
({
action
:
i
,
value
:
item
[
i
]
*
1
,
value
:
parseInt
(
item
[
i
])
?
item
[
i
]
*
1
:
0
,
rateAction
:
'转化率'
,
rate
:
(
(
item
.
转化人数
/
item
.
触达人数
)
*
100
).
toFixed
(
2
)
+
'%'
rate
:
(
item
.
转化人数
/
item
.
触达人数
)
*
100
?
((
item
.
转化人数
/
item
.
触达人数
)
*
100
).
toFixed
(
2
)
+
'%'
:
0
+
'%'
});
}
else
{
if
(
i
!=
'线索转化收益'
)
{
obj
.
unshift
({
action
:
i
,
value
:
item
[
i
]
?
item
[
i
]
*
1
:
0
value
:
parseInt
(
item
[
i
])
?
item
[
i
]
*
1
:
0
});
}
}
...
...
@@ -204,6 +204,7 @@ export default {
justify-content
:
space-between
;
.left
{
width
:
37%
;
min-width
:
530px
;
height
:
425px
;
background
:
#edf3ff
;
margin-right
:
5px
;
...
...
@@ -227,7 +228,7 @@ export default {
height
:
82px
;
p
{
&:nth-of-type(1)
{
width
:
164px
;
text-align
:
center
;
height
:
40px
;
font-size
:
34px
;
font-family
:
DINAlternate-Bold
,
DINAlternate
;
...
...
@@ -270,6 +271,7 @@ export default {
position
:
relative
;
background
:
url('~@/assets/img/fuunelBg1.png')
no-repeat
;
background-size
:
cover
;
padding-right
:
10px
;
.detail
{
position
:
absolute
;
width
:
83px
;
...
...
@@ -300,7 +302,8 @@ export default {
}
.allPlan_content
{
display
:
flex
;
.left
{
width
:
100%
;
.allPlan_content_left
{
display
:
flex
;
width
:
36%
;
height
:
56px
;
...
...
@@ -311,7 +314,6 @@ export default {
font-family
:
PingFangSC-Regular
,
PingFang
SC
;
margin-top
:
48px
;
padding-left
:
27px
;
background
:
transparent
;
.icon
{
width
:
56px
;
height
:
56px
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment