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
04e8d7a8
Commit
04e8d7a8
authored
Apr 26, 2021
by
liuchenxi
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
触达效果-----
parent
e85752ef
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
198 additions
and
66 deletions
+198
-66
index.html
index.html
+1
-0
index.vue
src/components/layout/index.vue
+2
-12
ecmApi.js
src/service/api/ecmApi.js
+3
-1
marketing.js
src/store/modules/marketing.js
+2
-1
list.vue
src/views/ecm/list.vue
+3
-1
touch-clue.vue
src/views/ecm/touch-clue.vue
+88
-33
description.vue
src/views/ecm/touch-components/description.vue
+3
-6
market-list.vue
src/views/ecm/touch-components/market-list.vue
+18
-7
touch-charts.vue
src/views/ecm/touch-components/touch-charts.vue
+40
-0
touch-effect.vue
src/views/ecm/touch-effect.vue
+38
-5
No files found.
index.html
View file @
04e8d7a8
...
...
@@ -29,6 +29,7 @@
<script
src=
"//web-1251519181.file.myqcloud.com/components/member-group.2.2.30.js"
></script>
<script
src=
"//web-1251519181.file.myqcloud.com/components/store-card.2.0.30.js"
></script>
<!-- 门店选择器 -->
<script
src=
"//web-1251519181.file.myqcloud.com/components/store-new.2.0.71.js"
></script>
<!-- 新版门店选择器 -->
<script
src=
"//web-1251519181.file.myqcloud.com/components/store-group.2.0.10.js"
></script>
<!-- 门店选择器 -->
<script
src=
"//web-1251519181.file.myqcloud.com/components/confirm-people.2.0.06.js"
></script>
<script
src=
"//web-1251519181.file.myqcloud.com/components/people.2.0.43.js"
></script>
<script
src=
"//web-1251519181.file.myqcloud.com/components/export-excel.2.0.16.js"
></script>
<!-- 数据导出 -->
...
...
src/components/layout/index.vue
View file @
04e8d7a8
...
...
@@ -14,7 +14,7 @@
<span>
{{
contentTitle
}}
</span>
<div
v-html=
"layoutTips"
class=
"layout--tips--wrap"
></div>
</div>
<div
v-if=
"$route.path.indexOf('ecm') >= 0 &&
xsxsFlag == 1
"
class=
"intro_wrap"
><img
:src=
"require('@/assets/img/introlIcon.png')"
class=
"introlIcon"
alt=
""
/><span
class=
"intro"
@
click=
"() => (drawer = true)"
>
指标说明
</span></div>
<div
v-if=
"$route.path.indexOf('ecm') >= 0 &&
$store.state.marketing.xsxsFlag
"
class=
"intro_wrap"
><img
:src=
"require('@/assets/img/introlIcon.png')"
class=
"introlIcon"
alt=
""
/><span
class=
"intro"
@
click=
"() => (drawer = true)"
>
指标说明
</span></div>
</h3>
</div>
<div
class=
"layout-content__wrap"
>
...
...
@@ -31,7 +31,6 @@
<
script
>
import
asideMenu
from
'../aside-menu'
;
import
description
from
'@/views/ecm/touch-components/description.vue'
;
import
{
getXsxsFalg
}
from
'@/service/api/ecmApi.js'
;
export
default
{
components
:
{
asideMenu
,
...
...
@@ -44,8 +43,7 @@ export default {
leftModulesName
:
'公众号配置'
,
bodyHeight
:
0
,
drawer
:
false
,
direction
:
'rtl'
,
xsxsFlag
:
0
direction
:
'rtl'
};
},
mounted
()
{
...
...
@@ -81,19 +79,11 @@ export default {
// 折叠事件
collapseTagHandler
(
val
)
{
this
.
collapseFlag
=
val
;
},
setXsxsFlag
()
{
getXsxsFalg
().
then
(
res
=>
{
this
.
xsxsFlag
=
res
.
result
;
});
}
},
watch
:
{
$route
:
{
handler
:
function
(
to
)
{
if
(
to
.
path
.
indexOf
(
'ecm'
)
>=
0
)
{
this
.
setXsxsFlag
();
}
this
.
drawer
=
false
;
},
immediate
:
true
...
...
src/service/api/ecmApi.js
View file @
04e8d7a8
...
...
@@ -47,6 +47,7 @@ export const exportCurrentSendDetails = config.api + PREFIX + 'export-current-se
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
ecmPlanTouchConfig
=
params
=>
requests
(
PREFIX
+
'ecmPlanTouchConfig'
,
params
);
// 智能营销--导购线索
export
const
ecmGuideCluesColumnDiagram
=
params
=>
requests
(
PREFIX
+
'ecmGuideCluesColumnDiagram'
,
params
);
export
const
ecmGuideCluesTable
=
params
=>
requests
(
PREFIX
+
'ecmGuideCluesTable'
,
params
);
...
...
@@ -59,7 +60,8 @@ export const ecmGuideCluesTouchEffectTabHead = params => requests(PREFIX + 'ecmG
export
const
ecmHeadCluesColumnDiagram
=
params
=>
requests
(
PREFIX
+
'ecmHeadCluesColumnDiagram'
,
params
);
export
const
ecmHeadGuideCluesTable
=
params
=>
requests
(
PREFIX
+
'ecmHeadGuideCluesTable'
,
params
);
export
const
ecmHeadCluesTaskTab
=
params
=>
requests
(
PREFIX
+
'ecmHeadCluesTaskTab'
,
params
);
// 表格
export
const
ecmHeadCluesTaskTabHead
=
params
=>
requests
(
PREFIX
+
'ecmHeadCluesTaskTabHead'
,
params
);
//表头
export
const
ecmHeadCluesTaskTabHead
=
params
=>
requests
(
PREFIX
+
'ecmHeadCluesTaskTabHead'
,
params
);
//表头1 计划整体
export
const
ecmGuideCluesTouchEffectTabTotalHead1
=
params
=>
requests
(
PREFIX
+
'ecmGuideCluesTouchEffectTabTotalHead1'
,
params
);
//表头2 区域合计
export
const
getUseStoredFalg
=
params
=>
requests
(
PREFIX
+
'get-ecm-store-flag'
,
params
);
...
...
src/store/modules/marketing.js
View file @
04e8d7a8
...
...
@@ -15,7 +15,8 @@ const state = {
layoutTips
:
''
,
isShowSelf
:
false
,
// 展示是否显示 '仅看本人' btn 在app.vue调用 每次刷新都会获取
openFlag
:
false
,
// 列表是否显示创建人
appletEnable
:
false
// 小程序是否可用
appletEnable
:
false
,
// 小程序是否可用,
xsxsFlag
:
false
// 是否开启销售线索
};
// getters
...
...
src/views/ecm/list.vue
View file @
04e8d7a8
...
...
@@ -176,7 +176,7 @@ export default {
formatter
(
row
)
{
let
openFlag
=
JSON
.
parse
(
row
.
analyseJson
);
if
(
!
openFlag
)
openFlag
=
{};
return
openFlag
.
open_flag
==
0
||
(
!
row
.
ecmTranIncome
&&
row
.
ecmTranIncome
!=
0
)
?
'--'
:
row
.
ecmTranIncome
;
return
openFlag
.
open_flag
==
0
||
(
!
row
.
ecmTranIncome
&&
row
.
ecmTranIncome
!=
0
)
?
'--'
:
row
.
ecmTranIncome
.
toFixed
(
2
)
;
}
}
],
...
...
@@ -272,6 +272,7 @@ export default {
// 是否开启销售线索
getXsxsFalg
().
then
(
res
=>
{
this
.
xsxsFlag
=
res
.
result
;
this
.
$store
.
state
.
marketing
.
xsxsFlag
=
res
.
result
;
if
(
this
.
xsxsFlag
==
0
)
{
let
arr
=
[];
this
.
tableHeader
.
forEach
(
item
=>
{
...
...
@@ -290,6 +291,7 @@ export default {
computed
:
{
isOpenFlag
(
item
)
{
return
item
=>
{
if
(
!
item
)
return
false
;
item
=
JSON
.
parse
(
item
);
if
(
!
item
)
item
=
{};
if
(
item
.
open_flag
==
0
)
{
...
...
src/views/ecm/touch-clue.vue
View file @
04e8d7a8
...
...
@@ -8,10 +8,12 @@
<div
class=
"dm-wrap area"
>
<div
class=
"areatitle"
>
<span
class=
"txt"
>
区域详情
</span>
<vue-gic-store-group
:options=
"options"
:isAdd=
"isAdd"
:uuid
.
sync=
"uuid"
ref=
"storeGroup"
></vue-gic-store-group>
</div>
<div
class=
"tabs"
v-if=
"type == 1"
>
<div
class=
"tab1"
>
<span
v-for=
"(item, index) in listTabs"
:key=
"index"
:class=
"
{ active: index == listTabsIndex }" @click="changeListTab(index)">
{{
item
}}
</span>
<div
class=
"line"
:class=
"
{ lineActive: listTabsIndex == 1 }">
</div>
</div>
<div
class=
"tab2"
>
<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>
...
...
@@ -31,7 +33,7 @@
</template>
<
script
>
import
{
ecmGuideCluesTable
,
ecmHeadCluesTaskTab
,
ecmHeadGuideCluesTable
,
ecmHeadCluesTaskTabHead
,
ecmGuideCluesTaskTable
,
ecmGuideCluesTouchEffectTotalTab
,
ecmGuideCluesTouchEffectTabTotalHead
,
ecmGuideCluesTouchEffectTab
,
ecmGuideCluesTouchEffectTabHead
}
from
'@/service/api/ecmApi.js'
;
import
{
ecmGuideCluesTable
,
ecmHeadCluesTaskTab
,
ecmHeadGuideCluesTable
,
ecmHeadCluesTaskTabHead
,
ecmGuideCluesT
ouchEffectTabTotalHead1
,
ecmGuideCluesT
askTable
,
ecmGuideCluesTouchEffectTotalTab
,
ecmGuideCluesTouchEffectTabTotalHead
,
ecmGuideCluesTouchEffectTab
,
ecmGuideCluesTouchEffectTabHead
}
from
'@/service/api/ecmApi.js'
;
import
marketList
from
'@/views/ecm/touch-components/market-list.vue'
;
import
touchCharts
from
'@/views/ecm/touch-components/touch-charts.vue'
;
export
default
{
...
...
@@ -94,8 +96,13 @@ export default {
pageSize
:
20
,
total
:
0
,
tableFirstData
:
{},
headClueTableFirstData
:
[],
// 后台线索的表头
touchOrderBy
:
''
,
taskOrderBy
:
''
taskOrderBy
:
''
,
uuid
:
''
,
// 新增传空,编辑必传,
options
:
[
0
,
4
,
5
],
// 0 全部 1 门店类型 2门店标签 3 门店区域 4 门店分组 5 部分门店
isAdd
:
true
,
isHeade2
:
false
};
},
mounted
()
{
...
...
@@ -103,11 +110,16 @@ export default {
let
name
;
let
planId
=
this
.
$route
.
query
.
id
;
this
.
type
=
this
.
$route
.
query
.
type
;
if
(
this
.
type
==
1
)
name
=
'导购线索'
;
else
if
(
this
.
type
==
2
)
name
=
'后台线索'
;
this
.
$store
.
commit
(
'mutations_breadcrumb'
,
[{
name
:
'营销管理'
,
path
:
''
},
{
name
:
'智能营销'
,
path
:
'/ecm'
},
{
name
:
`
${
planName
}
- 触达效果`
,
path
:
`/ecm/touch/
${
planId
}
?name=
${
planName
}
`
},
{
name
}]);
// eslint-disable-line
this
.
getMarketList
();
this
.
getTableFirstData
();
if
(
this
.
type
==
2
)
{
this
.
getTableFirstData
();
this
.
getTableFirstData
(
true
);
// 后台线索调第二个表头接口
name
=
'后台线索'
;
}
else
{
name
=
'导购线索'
;
this
.
getTableFirstData
();
}
this
.
$store
.
commit
(
'mutations_breadcrumb'
,
[{
name
:
'营销管理'
,
path
:
''
},
{
name
:
'智能营销'
,
path
:
'/ecm'
},
{
name
:
`
${
planName
}
- 触达效果`
,
path
:
`/ecm/touch/
${
planId
}
?name=
${
planName
}
`
},
{
name
}]);
// eslint-disable-line
},
methods
:
{
handleSizeChange
(
val
)
{
...
...
@@ -120,12 +132,14 @@ export default {
this
.
getTableList
();
},
changeTabs
(
index
)
{
if
(
this
.
listTabsIndex
==
1
)
{
if
(
this
.
tabsIndex
==
index
)
return
;
this
.
tabsIndex
=
index
;
}
else
{
if
(
this
.
taskTabIndex
==
index
)
return
;
this
.
taskTabIndex
=
index
;
if
(
this
.
type
==
1
)
{
if
(
this
.
listTabsIndex
==
1
)
{
if
(
this
.
tabsIndex
==
index
)
return
;
this
.
tabsIndex
=
index
;
}
else
{
if
(
this
.
taskTabIndex
==
index
)
return
;
this
.
taskTabIndex
=
index
;
}
}
this
.
getTableFirstData
();
},
...
...
@@ -161,16 +175,20 @@ export default {
fixed
:
'left'
,
formatter
(
row
)
{
let
color
=
'#F0F5FF'
;
let
textColor
=
'#606266'
;
if
(
row
.
index
==
1
)
{
color
=
'#F5222D'
;
textColor
=
'white'
;
}
else
if
(
row
.
index
==
2
)
{
color
=
'#FAAD14'
;
textColor
=
'white'
;
}
else
if
(
row
.
index
==
3
)
{
color
=
'#FFCB48'
;
textColor
=
'white'
;
}
else
if
(
!
row
.
index
)
{
return
'--'
;
}
return
`<span style="background:
${
color
}
;width: 16px; display: inline-block; text-align: center; line-height:16px">
${
row
.
index
}
</span>`
;
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'
},
...
...
@@ -216,7 +234,7 @@ export default {
},
getTableList
()
{
let
meth
;
let
params
=
{
ecmPlanId
:
this
.
$route
.
query
.
id
,
pageNum
:
this
.
currentPage
,
pageSize
:
this
.
pageSize
,
orderBy
:
this
.
listTabsIndex
==
1
?
this
.
touchOrderBy
:
this
.
taskOrderBy
};
let
params
=
{
ecmPlanId
:
this
.
$route
.
query
.
id
,
pageNum
:
this
.
currentPage
,
pageSize
:
this
.
pageSize
,
orderBy
:
this
.
listTabsIndex
==
1
?
this
.
touchOrderBy
:
this
.
taskOrderBy
,
storeWidgetKey
:
this
.
uuid
};
if
(
this
.
type
==
2
)
{
// 后台线索
meth
=
ecmHeadCluesTaskTab
;
...
...
@@ -238,15 +256,22 @@ export default {
}
}
}
this
.
tableList
=
[];
meth
(
params
).
then
(
res
=>
{
this
.
tableList
=
[];
if
(
!
res
.
result
.
result
||
!
res
.
result
.
result
.
length
)
{
return
;
}
if
(
this
.
currentPage
==
1
&&
this
.
listTabsIndex
!=
0
)
{
// 任务完成情况无表头
let
resetArr
=
[];
resetArr
[
0
]
=
this
.
tableFirstData
;
if
(
this
.
type
==
2
)
{
this
.
headClueTableFirstData
.
forEach
(
item
=>
{
if
(
item
.
storeName
==
'区域合计'
)
resetArr
[
1
]
=
item
;
else
if
(
item
.
storeName
==
'计划整体'
)
resetArr
[
0
]
=
item
;
});
}
else
{
resetArr
[
0
]
=
this
.
tableFirstData
;
}
res
.
result
.
result
&&
(
this
.
tableList
=
resetArr
.
concat
(
res
.
result
.
result
));
}
else
{
this
.
tableList
=
res
.
result
.
result
;
...
...
@@ -256,11 +281,16 @@ export default {
});
this
.
getTableHeader
();
},
getTableFirstData
()
{
getTableFirstData
(
head2
)
{
let
meth
;
let
params
=
{
ecmPlanId
:
this
.
$route
.
query
.
id
};
if
(
this
.
type
==
2
)
meth
=
ecmHeadCluesTaskTabHead
;
else
{
if
(
this
.
type
==
2
)
{
// 后台线索 要调两个表头接口
if
(
head2
)
{
this
.
isHeade2
=
true
;
meth
=
ecmGuideCluesTouchEffectTabTotalHead1
;
}
else
meth
=
ecmHeadCluesTaskTabHead
;
}
else
{
if
(
this
.
listTabsIndex
==
1
)
{
if
(
this
.
tabsIndex
==
0
)
{
meth
=
ecmGuideCluesTouchEffectTabTotalHead
;
...
...
@@ -276,8 +306,17 @@ export default {
meth
(
params
).
then
(
res
=>
{
let
data
=
res
.
result
;
data
.
storeName
=
'合计'
;
this
.
tableFirstData
=
res
.
result
;
this
.
getTableList
();
if
(
this
.
type
==
2
&&
!
head2
)
{
data
.
storeName
=
'计划整体'
;
}
else
if
(
this
.
type
==
2
&&
head2
)
{
data
.
storeName
=
'区域合计'
;
}
this
.
tableFirstData
=
data
;
if
(
this
.
type
==
2
)
{
this
.
headClueTableFirstData
.
push
(
data
);
}
if
(
this
.
type
==
2
&&
head2
)
this
.
getTableList
();
else
if
(
this
.
type
==
1
)
this
.
getTableList
();
});
},
sortChange
(
column
)
{
...
...
@@ -310,6 +349,11 @@ export default {
'line-height'
:
'16px'
};
}
},
watch
:
{
uuid
(
val
)
{
console
.
log
(
val
);
}
}
};
</
script
>
...
...
@@ -328,6 +372,9 @@ export default {
font-size
:
16px
;
padding-left
:
32px
;
margin-bottom
:
8px
;
display
:
flex
;
justify-content
:
space-between
;
padding-right
:
20px
;
.txt
{
font-family
:
PingFangSC-Medium
,
PingFang
SC
;
width
:
64px
;
...
...
@@ -339,6 +386,7 @@ export default {
}
.tabs
{
.tab2
{
cursor
:
pointer
;
margin-top
:
20px
;
display
:
flex
;
padding-left
:
22px
;
...
...
@@ -369,30 +417,35 @@ export default {
.tab1
{
height
:
40px
;
font-size
:
0
;
padding
:
14px
0
12px
33px
;
padding
:
0
0
0
33px
;
box-sizing
:
border-box
;
border-bottom
:
1px
solid
#dcdfe6
;
cursor
:
pointer
;
position
:
relative
;
.line
{
position
:
absolute
;
width
:
98px
;
height
:
2px
;
background
:
#1890ff
;
bottom
:
0px
;
left
:
26px
;
transition
:
all
0.3s
;
&.lineActive
{
left
:
156px
;
}
}
.active
{
color
:
#1890ff
;
&::before
{
content
:
''
;
position
:
absolute
;
width
:
100%
;
height
:
2px
;
background
:
#1890ff
;
bottom
:
-11px
;
left
:
-20px
;
}
}
span
{
font-size
:
14px
;
font-family
:
PingFangSC-Regular
,
PingFang
SC
;
font-weight
:
400
;
color
:
#606266
;
line-height
:
14
px
;
line-height
:
40
px
;
display
:
inline-block
;
width
:
96px
;
height
:
1
4px
;
height
:
1
00%
;
position
:
relative
;
&:nth-child(1)
{
margin-right
:
47px
;
...
...
@@ -406,9 +459,11 @@ export default {
}
.area
{
padding
:
19px
0
20px
0
!important
;
margin-top
:
0
!important
;
}
.draw_wrap
{
padding
:
16px
20px
32px
!important
;
margin-bottom
:
10px
!important
;
}
.dm-pagination
{
margin
:
20px
15px
0
0
;
...
...
src/views/ecm/touch-components/description.vue
View file @
04e8d7a8
<
template
>
<!--文字说明-->
<el-drawer
title=
"
数据指标说明"
:visible
.
sync=
"drawer"
:direction=
"direction"
custom-class=
"touch_drawer h65
0"
v-if=
"contentTitle == '触达效果'"
>
<el-drawer
title=
"
触达效果说明"
:visible
.
sync=
"drawer"
:direction=
"direction"
custom-class=
"touch_drawer h67
0"
v-if=
"contentTitle == '触达效果'"
>
<ul
class=
"content"
>
<li>
数据更新频率:1天1次
</li>
<li>
...
...
@@ -34,7 +34,7 @@
③ 一个触达转化消费,在多个导购触达任务的收益计算有效期内的,该笔转化只记给第一个触达任务;
<br
/>
④ 转化收益只计销售单,不看退货单和换货单;金额是应付还是实付看ERP传入的值。
<br
/>
⑤『触达率』:触达人数 / 计划触达人数
<br
/>
⑥『转化率』:转化人数 / 触达人数
⑥『转化率』:转化人数 / 触达人数
; 参照组不存在触达人数,转化率 = 转化人数 / 计划人数
</p>
</div>
</li>
...
...
@@ -89,7 +89,7 @@
</li>
</ul>
</el-drawer>
<el-drawer
title=
"【
导购
线索】说明"
:visible
.
sync=
"drawer"
:direction=
"direction"
custom-class=
"touch_drawer h670"
v-else-if=
"contentTitle == '后台线索'"
>
<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>
...
...
@@ -172,9 +172,6 @@ export default {
.h850
{
height
:
850px
!important
;
}
.h650
{
height
:
650px
!important
;
}
.h670
{
height
:
670px
!important
;
}
...
...
src/views/ecm/touch-components/market-list.vue
View file @
04e8d7a8
...
...
@@ -2,7 +2,7 @@
<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
class=
"right"
v-if=
"isRepeat"
>
批次合计:
{{
batchNum
}}
/ 最新批次时间:
{{
batchTimes
}}
</div>
</div>
<div
class=
"middle"
v-for=
"(item, index) in data"
:key=
"index"
>
<template
v-if=
"item.isSales == 1"
>
...
...
@@ -20,7 +20,7 @@
</div>
</
template
>
<!--非线索页列表-->
<div
class=
"right"
:class=
"[isCluePage ? 'cluePage' : '']"
>
<div
class=
"right"
:class=
"[isCluePage ? 'cluePage' : '']"
ref=
"right"
>
<div
v-if=
"!isCluePage"
>
<p>
计划人次
</p>
<p>
{{ item.planMbrTimes ? item.planMbrTimes.toLocaleString() : 0 }}
</p>
...
...
@@ -35,15 +35,16 @@
</p>
<p>
{{ item.taskRate ? item.taskRate.toFixed(2) + '%' : 0 }}
</p>
</div>
<div>
<div
v-if=
"isCluePage || item.isSales == 1"
class=
"touchMbr"
>
<p>
触达人数
<span>
(触达率 {{ item.touchRate ? item.touchRate + '%' : 0 + '%' }})
</span>
</p>
<p>
{{ item.touchMbrNum ? item.touchMbrNum.toLocaleString() : 0 }}
</p>
</div>
<div>
<div
v-else
class=
"touchMbr touchMbr2"
>
- -
</div>
<div
class=
"convMbr"
>
<p>
转化人数
<span
:class=
"{ active: item.isSales == 1 && data[0].transformRate < data[1].transformRate }"
>
(转化率 {{ item.transformRate ? item.transformRate + '%' : 0 + '%' }})
</span>
转化人数
<span
:class=
"{ active: i
sReference && i
tem.isSales == 1 && data[0].transformRate < data[1].transformRate }"
>
(转化率 {{ item.transformRate ? item.transformRate + '%' : 0 + '%' }})
</span>
</p>
<p>
{{ item.convMbrNum ? item.convMbrNum.toLocaleString() : 0 }}
</p>
</div>
...
...
@@ -83,7 +84,9 @@ export default {
data
:
{
type
:
Array
,
default
:
()
=>
[]
}
},
batchTimes
:
String
,
batchNum
:
Number
|
String
},
computed
:
{
convSalesAmt
(
num
)
{
...
...
@@ -162,7 +165,6 @@ export default {
.icon
{
width
:
40px
;
height
:
40px
;
background
:
rgba
(
144
,
188
,
255
,
0.21
);
border-radius
:
4px
;
margin-right
:
15px
;
}
...
...
@@ -174,6 +176,7 @@ export default {
display
:
flex
;
justify-content
:
space-between
;
div
{
flex
:
1
;
p
{
&:nth-child(1)
{
font-size
:
14px
;
...
...
@@ -197,6 +200,14 @@ export default {
}
}
}
.touchMbr2
{
align-items
:
center
;
padding-top
:
19px
;
}
.convMbr
,
.touchMbr
{
flex
:
1.3
;
}
}
.cluePage
{
padding-left
:
65px
;
...
...
src/views/ecm/touch-components/touch-charts.vue
View file @
04e8d7a8
...
...
@@ -21,6 +21,7 @@ export default {
},
methods
:
{
draw
()
{
this
.
chartData
=
this
.
formatterData
(
this
.
chartData
);
let
valueArr
=
this
.
chartData
.
filter
(
item
=>
item
.
value
>=
0
);
let
rateArr
=
this
.
chartData
.
filter
(
item
=>
item
.
rate
>=
0
);
let
valueFlag
=
valueArr
.
every
(
item
=>
item
.
value
==
0
);
// value是否出现全为0的情况
...
...
@@ -78,6 +79,17 @@ export default {
},
grid
:
null
});
chart
.
axis
(
'value'
,
{
label
:
{
formatter
:
text
=>
{
let
num
=
Number
(
text
);
if
(
num
>=
10000
)
{
return
num
/
10000
+
'万'
;
}
return
num
;
}
}
});
chart
.
interval
()
.
position
(
'date*value'
)
...
...
@@ -112,6 +124,34 @@ export default {
});
this
.
draw
();
});
},
allDate
()
{
let
arr
=
[];
let
date
=
new
Date
().
getTime
();
let
oneDay
=
86400000
;
for
(
let
i
=
1
;
i
<=
15
;
i
++
)
{
let
item
=
new
Date
(
date
-
oneDay
*
i
).
toLocaleString
(
'chinese'
,
{
hour12
:
false
,
year
:
'numeric'
,
month
:
'2-digit'
,
day
:
'2-digit'
,
hour
:
'2-digit'
,
minute
:
'2-digit'
,
second
:
'2-digit'
});
item
=
item
.
replace
(
/
[\/]
/g
,
'-'
).
split
(
' '
);
let
obj
=
[
{
date
:
item
[
0
],
value
:
0
,
name
:
'触达人数'
},
{
date
:
item
[
0
],
value
:
0
,
name
:
'转化人数'
},
{
date
:
item
[
0
],
rate
:
0
,
name
:
'线索转化收益'
}
];
arr
.
unshift
(...
obj
);
}
return
arr
;
},
formatterData
(
chartData
)
{
let
dateArr
=
this
.
allDate
();
chartData
.
forEach
(
item
=>
{
dateArr
.
forEach
(
el
=>
{
if
(
item
.
date
==
el
.
date
&&
item
.
name
==
el
.
name
)
{
if
(
el
.
name
==
'线索转化收益'
)
el
.
rate
=
item
.
rate
.
toFixed
(
2
);
else
el
.
value
=
item
.
value
;
}
});
});
return
dateArr
;
}
}
};
...
...
src/views/ecm/touch-effect.vue
View file @
04e8d7a8
...
...
@@ -5,7 +5,7 @@
<h2>
触达效果
</h2>
</div>
<touch-charts
:type=
"0"
/>
<market-list
v-if=
"marketListData.length"
:isRepeat=
"
true"
:data=
"marketListData
"
/>
<market-list
v-if=
"marketListData.length"
:isRepeat=
"
isRepeat"
:data=
"marketListData"
:isReference=
"isReference"
:batchNum=
"batchNum"
:batchTimes=
"batchTime
"
/>
</div>
<div
class=
"dm-wrap table"
>
<div
class=
"title"
>
...
...
@@ -23,7 +23,7 @@
</div>
</div>
<div
class=
"bottom"
>
<funnel
v-if=
"funnelData.length"
nodeName=
"funnel1"
:colorArr=
"['#
5584FF', '#719FFF', '#90BC
FF']"
:data=
"funnelData[0]"
></funnel>
<funnel
v-if=
"funnelData.length"
nodeName=
"funnel1"
:colorArr=
"['#
2F54EB', '#636AF7', '#8F83
FF']"
:data=
"funnelData[0]"
></funnel>
</div>
</div>
<div
class=
"right"
>
...
...
@@ -68,7 +68,8 @@
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
{
ecmTouchEffectTable
,
ecmTouchEffectFunnelChart
}
from
'@/service/api/ecmApi.js'
;
import
{
ecmTouchEffectTable
,
ecmTouchEffectFunnelChart
,
ecmPlanTouchConfig
}
from
'@/service/api/ecmApi.js'
;
// ecmPlanTouchConfig
export
default
{
name
:
'ecm'
,
data
()
{
...
...
@@ -77,7 +78,11 @@ export default {
funnelData
:
[],
clueRate
:
[],
loading
:
true
,
ecmPlanId
:
''
ecmPlanId
:
''
,
isRepeat
:
false
,
// 是否重复营销
isReference
:
false
,
batchNum
:
0
,
// 批次数量
batchTime
:
''
// 批次时间
};
},
components
:
{
...
...
@@ -91,6 +96,7 @@ export default {
this
.
$store
.
commit
(
'mutations_breadcrumb'
,
[{
name
:
'营销管理'
,
path
:
''
},
{
name
:
'智能营销'
,
path
:
'/ecm'
},
{
name
:
`
${
planName
}
- 触达效果`
}]);
// eslint-disable-line
this
.
getMarketList
();
this
.
getFunnelData
();
this
.
getTouchConfig
();
},
methods
:
{
toClue
(
type
)
{
...
...
@@ -104,7 +110,7 @@ export default {
ecmTouchEffectTable
({
ecmPlanId
:
this
.
ecmPlanId
}).
then
(
res
=>
{
this
.
marketListData
=
res
.
result
.
map
(
item
=>
{
item
.
touchRate
=
parseFloat
(((
item
.
touchMbrNum
/
item
.
planMbrNum
)
*
100
).
toFixed
(
2
));
item
.
transformRate
=
parseFloat
(((
item
.
convMbrNum
/
item
.
touch
MbrNum
)
*
100
).
toFixed
(
2
));
item
.
transformRate
=
parseFloat
(((
item
.
convMbrNum
/
item
.
plan
MbrNum
)
*
100
).
toFixed
(
2
));
return
item
;
});
});
...
...
@@ -156,6 +162,31 @@ export default {
return
obj
;
});
return
obj
;
},
getTouchConfig
()
{
ecmPlanTouchConfig
({
ecmPlanId
:
this
.
ecmPlanId
}).
then
(
res
=>
{
this
.
batchNum
=
res
.
result
.
times
?
res
.
result
.
times
:
0
;
if
(
res
.
result
.
lastTime
)
{
this
.
batchTime
=
new
Date
(
parseInt
(
res
.
result
.
lastTime
)).
toLocaleString
(
'zh'
,
{
hour12
:
false
}).
replace
(
/
[\/]
/g
,
'-'
);
}
else
{
this
.
batchTime
=
'--'
;
}
res
.
result
.
effectType
=
1
;
// res.result.analyseJson = null;
let
analyseJson
=
JSON
.
parse
(
res
.
result
.
analyseJson
);
if
(
analyseJson
&&
analyseJson
.
crowd_flag
==
1
)
{
// 是否开启了参照组开关
this
.
isReference
=
true
;
}
else
{
this
.
isReference
=
false
;
this
.
marketListData
.
forEach
((
item
,
index
)
=>
{
// 没开启参照组的时候删除那一组信息
if
(
item
.
isSales
==
0
)
this
.
marketListData
.
splice
(
index
,
1
);
});
}
if
(
res
.
result
.
effectType
==
1
)
this
.
isRepeat
=
true
;
else
this
.
isRepeat
=
false
;
});
}
}
};
...
...
@@ -163,6 +194,7 @@ export default {
<
style
lang=
"scss"
scoped
>
.dm-wrap
{
padding
:
16px
20px
27px
!important
;
margin-bottom
:
10px
!important
;
.title
{
padding-left
:
12px
;
margin-bottom
:
36px
;
...
...
@@ -176,6 +208,7 @@ export default {
}
}
.table
{
margin-top
:
0
!important
;
.title
{
padding
:
3px
0
0
12px
;
font-size
:
16px
;
...
...
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