|
|
<template>
|
|
|
<div class="content">
|
|
|
<div class="import" @click="dialogVisible = true">
|
|
|
<img src="@/assets/images/导入.png" alt="" />
|
|
|
<span>任务知识导入</span>
|
|
|
</div>
|
|
|
<!-- <div v-if="knowledgeFlag">
|
|
|
<a
|
|
|
href="https://zhuanlan.zhihu.com/p/400319684"
|
|
|
target="_blank"
|
|
|
rel="noopener noreferrer"
|
|
|
>https://zhuanlan.zhihu.com/p/400319684</a
|
|
|
>
|
|
|
<br />
|
|
|
</div> -->
|
|
|
<div>
|
|
|
<div class="caseBack">
|
|
|
<div class="title">
|
|
|
<img src="@/assets/images/caseIcon.png" alt="" />
|
|
|
<span>案例背景:</span>
|
|
|
</div>
|
|
|
<span style="line-height: 25px; font-size: 14px">
|
|
|
以下是某APP注册用户14天的登录数据,请展开留存分析。
|
|
|
</span>
|
|
|
<div style="margin-top: 10px; display: flex">
|
|
|
<el-table
|
|
|
:data="fileTable1"
|
|
|
style="width: 1250px"
|
|
|
border
|
|
|
:header-cell-style="{
|
|
|
color: '#fff',
|
|
|
fontSize: '14px',
|
|
|
backgroundColor: '#6A7DE9!important',
|
|
|
}"
|
|
|
|
|
|
>
|
|
|
<el-table-column label="日期" align="center" prop="date">
|
|
|
</el-table-column>
|
|
|
<el-table-column label="新增用户数" align="center" prop="addNum" width="120">
|
|
|
</el-table-column>
|
|
|
<el-table-column label="次日" align="center" prop="day2">
|
|
|
</el-table-column>
|
|
|
<el-table-column label="3日" align="center" prop="day3">
|
|
|
</el-table-column>
|
|
|
<el-table-column label="4日" align="center" prop="day4">
|
|
|
</el-table-column>
|
|
|
<el-table-column label="5日" align="center" prop="day5">
|
|
|
</el-table-column>
|
|
|
<el-table-column label="6日" align="center" prop="day6">
|
|
|
</el-table-column>
|
|
|
<el-table-column label="7日" align="center" prop="day7">
|
|
|
</el-table-column>
|
|
|
<el-table-column label="8日" align="center" prop="day8">
|
|
|
</el-table-column>
|
|
|
<el-table-column label="9日" align="center" prop="day9">
|
|
|
</el-table-column>
|
|
|
<el-table-column label="10日" align="center" prop="day10">
|
|
|
</el-table-column>
|
|
|
<el-table-column label="11日" align="center" prop="day11">
|
|
|
</el-table-column>
|
|
|
<el-table-column label="12日" align="center" prop="day12">
|
|
|
</el-table-column>
|
|
|
<el-table-column label="13日" align="center" prop="day13">
|
|
|
</el-table-column>
|
|
|
<el-table-column label="14日" align="center" prop="day14">
|
|
|
</el-table-column>
|
|
|
</el-table>
|
|
|
<div class="download" @click="downloadData">下载数据</div>
|
|
|
</div>
|
|
|
<span style="line-height: 25px; font-size: 14px">
|
|
|
表格列指标释义:<br />
|
|
|
新增用户数,表示当日注册的用户数<br />
|
|
|
次日:当日注册的这批用户在次日有XX人访问<br />
|
|
|
3日:当日注册的这批用户在注册后的第3日有XX人访问<br />
|
|
|
7日:当日注册的这批用户在注册后的第7日有XX人访问
|
|
|
</span>
|
|
|
</div>
|
|
|
<div class="line"></div>
|
|
|
<div class="caseBack">
|
|
|
<div class="title">
|
|
|
<img src="@/assets/images/步骤.png" alt="" />
|
|
|
<span>第一步,留存率的计算</span>
|
|
|
</div>
|
|
|
<span style="line-height: 25px; font-size: 14px">
|
|
|
留存率是指:某日用户数在第N日仍启动该App的用户比例,留存分析即分析用户随时间变化的活跃情况。获取用户只是第一步,留住用户才是所有产品最终目标。<br />
|
|
|
请按照留存率的计算公式,补全空缺的数据,计算结果保留小数点后0位。
|
|
|
</span>
|
|
|
<div style="margin-top: 10px; display: flex">
|
|
|
<el-table
|
|
|
:data="step1Data"
|
|
|
style="width: 1450px"
|
|
|
border
|
|
|
:header-cell-style="{
|
|
|
color: '#fff',
|
|
|
fontSize: '14px',
|
|
|
backgroundColor: '#6A7DE9!important',
|
|
|
}"
|
|
|
>
|
|
|
<el-table-column label="日期" align="center" prop="date">
|
|
|
</el-table-column>
|
|
|
<el-table-column label="新增用户数" align="center" prop="addNum" width="120">
|
|
|
</el-table-column>
|
|
|
<el-table-column label="次日" align="center" prop="day2">
|
|
|
<template #default="scope">
|
|
|
<el-input
|
|
|
v-model="scope.row.params"
|
|
|
placeholder="输入"
|
|
|
style="width: 50px"
|
|
|
v-if="scope.$index == 12"
|
|
|
size="small"
|
|
|
>
|
|
|
</el-input
|
|
|
><span v-if="scope.$index == 12">%</span>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
<el-table-column label="3日" align="center" prop="day3">
|
|
|
<template #default="scope">
|
|
|
<el-input
|
|
|
v-model="scope.row.params"
|
|
|
placeholder="输入"
|
|
|
style="width: 50px"
|
|
|
v-if="scope.$index == 11"
|
|
|
size="small"
|
|
|
>
|
|
|
</el-input
|
|
|
><span v-if="scope.$index == 11">%</span>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
<el-table-column label="4日" align="center" prop="day4">
|
|
|
<template #default="scope">
|
|
|
<el-input
|
|
|
v-model="scope.row.params"
|
|
|
placeholder="输入"
|
|
|
style="width: 50px"
|
|
|
v-if="scope.$index == 10"
|
|
|
size="small"
|
|
|
>
|
|
|
</el-input
|
|
|
><span v-if="scope.$index == 10">%</span>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
<el-table-column label="5日" align="center" prop="day5">
|
|
|
<template #default="scope">
|
|
|
<el-input
|
|
|
v-model="scope.row.params"
|
|
|
placeholder="输入"
|
|
|
style="width: 50px"
|
|
|
v-if="scope.$index == 9"
|
|
|
size="small"
|
|
|
>
|
|
|
</el-input
|
|
|
><span v-if="scope.$index == 9">%</span>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
<el-table-column label="6日" align="center" prop="day6">
|
|
|
<template #default="scope">
|
|
|
<el-input
|
|
|
v-model="scope.row.params"
|
|
|
placeholder="输入"
|
|
|
style="width: 50px"
|
|
|
v-if="scope.$index == 8"
|
|
|
size="small"
|
|
|
>
|
|
|
</el-input
|
|
|
><span v-if="scope.$index == 8">%</span>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
<el-table-column label="7日" align="center" prop="day7">
|
|
|
<template #default="scope">
|
|
|
<el-input
|
|
|
v-model="scope.row.params"
|
|
|
placeholder="输入"
|
|
|
style="width: 50px"
|
|
|
v-if="scope.$index == 7"
|
|
|
size="small"
|
|
|
>
|
|
|
</el-input
|
|
|
><span v-if="scope.$index == 7">%</span>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
<el-table-column label="8日" align="center" prop="day8">
|
|
|
<template #default="scope">
|
|
|
<el-input
|
|
|
v-model="scope.row.params"
|
|
|
placeholder="输入"
|
|
|
style="width: 50px"
|
|
|
v-if="scope.$index == 6"
|
|
|
size="small"
|
|
|
>
|
|
|
</el-input
|
|
|
><span v-if="scope.$index == 6">%</span>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
<el-table-column label="9日" align="center" prop="day9">
|
|
|
<template #default="scope">
|
|
|
<el-input
|
|
|
v-model="scope.row.params"
|
|
|
placeholder="输入"
|
|
|
style="width: 50px"
|
|
|
v-if="scope.$index == 5"
|
|
|
size="small"
|
|
|
>
|
|
|
</el-input
|
|
|
><span v-if="scope.$index == 5">%</span>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
<el-table-column label="10日" align="center" prop="day10">
|
|
|
<template #default="scope">
|
|
|
<el-input
|
|
|
v-model="scope.row.params"
|
|
|
placeholder="输入"
|
|
|
style="width: 50px"
|
|
|
v-if="scope.$index == 4"
|
|
|
size="small"
|
|
|
>
|
|
|
</el-input
|
|
|
><span v-if="scope.$index == 4">%</span>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
<el-table-column label="11日" align="center" prop="day11">
|
|
|
<template #default="scope">
|
|
|
<el-input
|
|
|
v-model="scope.row.params"
|
|
|
placeholder="输入"
|
|
|
style="width: 50px"
|
|
|
v-if="scope.$index == 3"
|
|
|
size="small"
|
|
|
>
|
|
|
</el-input
|
|
|
><span v-if="scope.$index == 3">%</span>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
<el-table-column label="12日" align="center" prop="day12">
|
|
|
<template #default="scope">
|
|
|
<el-input
|
|
|
v-model="scope.row.params"
|
|
|
placeholder="输入"
|
|
|
style="width: 50px"
|
|
|
v-if="scope.$index == 2"
|
|
|
size="small"
|
|
|
>
|
|
|
</el-input
|
|
|
><span v-if="scope.$index == 2">%</span>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
<el-table-column label="13日" align="center" prop="day13">
|
|
|
<template #default="scope">
|
|
|
<el-input
|
|
|
v-model="scope.row.params"
|
|
|
placeholder="输入"
|
|
|
style="width: 50px"
|
|
|
v-if="scope.$index == 1"
|
|
|
size="small"
|
|
|
>
|
|
|
</el-input
|
|
|
><span v-if="scope.$index == 1">%</span>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
<el-table-column label="14日" align="center" prop="day14">
|
|
|
<template #default="scope">
|
|
|
<el-input
|
|
|
v-model="scope.row.params"
|
|
|
placeholder="输入"
|
|
|
style="width: 50px"
|
|
|
v-if="scope.$index == 0"
|
|
|
size="small"
|
|
|
>
|
|
|
</el-input
|
|
|
><span v-if="scope.$index == 0">%</span>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
</el-table>
|
|
|
<div class="submit" @click="step1Submit">提交</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
<div class="line"></div>
|
|
|
<div class="caseBack">
|
|
|
<div class="title">
|
|
|
<img src="@/assets/images/步骤.png" alt="" />
|
|
|
<span>第二步,留存分析常用口径计算</span>
|
|
|
</div>
|
|
|
<span style="line-height: 25px; font-size: 14px">
|
|
|
从时间维度划分,常见的的有:次日留存、3日留存、7日留存、14日留存、30日留存、60日留存。<br />
|
|
|
从用户维度划分,常见的的有:新用户留存、活跃留存。<br />
|
|
|
请按照第一步计算的表格数据,计算次日留存、3日留存、7日留存、14日留存的平均数,计算结果保留小数点后0位。
|
|
|
</span>
|
|
|
<div style="margin-top: 10px; display: flex">
|
|
|
<el-table
|
|
|
:data="step2Data"
|
|
|
style="width: 650px"
|
|
|
border
|
|
|
:header-cell-style="{
|
|
|
color: '#fff',
|
|
|
fontSize: '14px',
|
|
|
backgroundColor: '#6A7DE9!important',
|
|
|
}"
|
|
|
>
|
|
|
<el-table-column label="" align="center" prop="name">
|
|
|
</el-table-column>
|
|
|
<el-table-column label="次日" align="center" prop="description">
|
|
|
<template #default="scope">
|
|
|
<el-input
|
|
|
v-model="scope.row.params1"
|
|
|
placeholder="请输入"
|
|
|
style="width: 70px"
|
|
|
>
|
|
|
</el-input
|
|
|
><span>%</span>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
<el-table-column label="3日" align="center" prop="description">
|
|
|
<template #default="scope">
|
|
|
<el-input
|
|
|
v-model="scope.row.params2"
|
|
|
placeholder="请输入"
|
|
|
style="width: 70px"
|
|
|
>
|
|
|
</el-input
|
|
|
><span>%</span>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
<el-table-column label="7日" align="center" prop="description">
|
|
|
<template #default="scope">
|
|
|
<el-input
|
|
|
v-model="scope.row.params3"
|
|
|
placeholder="请输入"
|
|
|
style="width: 70px"
|
|
|
>
|
|
|
</el-input
|
|
|
><span>%</span>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
<el-table-column label="14日" align="center" prop="amount">
|
|
|
<template #default="scope">
|
|
|
<el-input
|
|
|
v-model="scope.row.params4"
|
|
|
placeholder="请输入"
|
|
|
style="width: 70px"
|
|
|
>
|
|
|
</el-input
|
|
|
><span>%</span>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
</el-table>
|
|
|
<div class="submit" @click="step2Submit">提交</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
<div class="line"></div>
|
|
|
<div class="caseBack">
|
|
|
<div class="title">
|
|
|
<img src="@/assets/images/步骤.png" alt="" />
|
|
|
<span>第三步,留存率可视化分析</span>
|
|
|
</div>
|
|
|
<span style="line-height: 25px; font-size: 14px">
|
|
|
以2021/8/1注册的新增的用户数据为例,绘制之后14日的留存率折线图:
|
|
|
</span>
|
|
|
<div class="draw" @click="draw">绘制</div>
|
|
|
<div style="margin-top: 10px; display: flex">
|
|
|
<div id="echarts" style="width: 400px; height: 300px"></div>
|
|
|
<div style="margin-left: 50px">
|
|
|
<p>通过图表分析,新增用户在哪天之后趋向于平稳</p>
|
|
|
<el-select
|
|
|
v-model="dayValue"
|
|
|
placeholder="请选择"
|
|
|
style="width: 120px"
|
|
|
size="default"
|
|
|
@change="handleChangeDay"
|
|
|
>
|
|
|
<el-option
|
|
|
v-for="item in dayOptions"
|
|
|
:key="item.value"
|
|
|
:label="item.label"
|
|
|
:value="item.value"
|
|
|
/>
|
|
|
</el-select>
|
|
|
<div class="analysis">
|
|
|
<div class="conclusion">分析结论:</div>
|
|
|
<span>
|
|
|
1、7日留存率,只有27%,流失率达到了73%,相对比较低,需要提供用户粘性;<br />
|
|
|
2、平缓之后,能够留存下来的客户,是公司的忠诚用户;<br />
|
|
|
3、14日的留存率,每天一直下降,需要找出原因。
|
|
|
</span>
|
|
|
</div>
|
|
|
<div
|
|
|
class="submit"
|
|
|
@click="step3Submit"
|
|
|
style="margin-top: 20px; margin-left: 0px"
|
|
|
>
|
|
|
提交
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
<div class="line"></div>
|
|
|
<div class="caseBack">
|
|
|
<div class="title">
|
|
|
<img src="@/assets/images/步骤.png" alt="" />
|
|
|
<span>第四步,平均留存分析</span>
|
|
|
</div>
|
|
|
<span style="line-height: 25px; font-size: 14px">
|
|
|
留存分析的适用场景:<br />
|
|
|
日留存率: <br />
|
|
|
快速判断产品是否迎合市场需求,比如新手对产品的UI设计、功能设置、新手引导等的体验是否满意,是否需做调整。<br />
|
|
|
快速判断用户粘性,比如用户是否更易受促销活动的影响等等。<br />
|
|
|
周留存率: <br />
|
|
|
判断用户忠诚度,用户此时对产品基本已有完整的体验。一整套流程体验下来,继续访问的用户可判断为潜在忠诚用户。<br />
|
|
|
分析用户再次访问的原因,找出产品最能巩固用户的点,且参考此点以一贯之,拓展应用到更多的用户身上,促使更多的用户留下来。<br />
|
|
|
月留存率:<br />
|
|
|
评估迭代与优化的效果。砍掉留存率低的产品功能,进行迭代优化。<br />
|
|
|
平均留存率的分析,需要结合公司不同时期,与行业平均水平进行对比,找出差距,分析相关原因,从而制定营销策略。
|
|
|
</span>
|
|
|
<div style="margin-top: 10px; display: flex">
|
|
|
<el-table
|
|
|
:data="step4Data"
|
|
|
style="width: 650px"
|
|
|
border
|
|
|
:header-cell-style="{
|
|
|
color: '#fff',
|
|
|
fontSize: '14px',
|
|
|
backgroundColor: '#6A7DE9!important',
|
|
|
}"
|
|
|
>
|
|
|
<el-table-column label="" align="center" prop="name">
|
|
|
</el-table-column>
|
|
|
<el-table-column label="次日" align="center" prop="data1">
|
|
|
</el-table-column>
|
|
|
<el-table-column label="3日" align="center" prop="data2">
|
|
|
</el-table-column>
|
|
|
<el-table-column label="7日" align="center" prop="data3">
|
|
|
</el-table-column>
|
|
|
<el-table-column label="14日" align="center" prop="data4">
|
|
|
</el-table-column>
|
|
|
</el-table>
|
|
|
</div>
|
|
|
</div>
|
|
|
<div class="line"></div>
|
|
|
<div class="caseBack">
|
|
|
<div class="title">
|
|
|
<img src="@/assets/images/步骤.png" alt="" />
|
|
|
<span>第五步,留存分析应用场景</span>
|
|
|
</div>
|
|
|
<span style="line-height: 25px; font-size: 14px">
|
|
|
日常工作中,留存分析常用于下述场景:
|
|
|
</span>
|
|
|
<div style="font-size: 14px; margin-top: 10px">
|
|
|
1. 了解一个渠道的质量<br />
|
|
|
可以使用「日留存」来衡量各渠道用户的表现,并以此作为衡量渠道质量的标准之一。如对不同渠道来源的用户进行次日留存、7日留存的对比(不同行业可能选择不同周期),
|
|
|
以此衡量不同渠道的用户留存情况。一般来说,留存情况较好可以反应这个渠道质量较好。
|
|
|
</div>
|
|
|
<div style="font-size: 14px; margin-top: 10px">
|
|
|
2. 判断运营手段/某项功能改动是否奏效<br />
|
|
|
当我们期待某个运营手段/某项功能可以期提升留存时,可以对通过分析该运营手段/功能,「覆盖到的新用户」和「未覆盖到的新用户」的留存率,对两部分用户的留存进行对比,来验证手段/功能的有效性。
|
|
|
以贴吧为例,该贴吧想检验“看贴”功能是否对新用户的留存是有提升效果,于是对同样来自A渠道的新用户(一部分使用了看贴功能,一部分没有使用看贴功能)进行留存对比。通过比较发现,使用过看贴功能的新用户,
|
|
|
三日留存率比未使用过该功能的新用户,多了10%以上。这说明“看贴”功能对新用户留存有着正向促进作用。
|
|
|
</div>
|
|
|
<div style="font-size: 14px; margin-top: 10px">
|
|
|
3. 衡量一个产品是否健康<br />
|
|
|
可以使用「周留存」、「月留存」等指标观察用户在平台上的粘性,衡量产品的健康情况。
|
|
|
</div>
|
|
|
</div>
|
|
|
<div class="line"></div>
|
|
|
</div>
|
|
|
<pop-modal :showModel="dialogVisible" @closePop="dialogVisible = false">
|
|
|
<template v-slot:content>
|
|
|
<div v-html="knowledgeHtml"></div>
|
|
|
</template>
|
|
|
</pop-modal>
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
<script setup>
|
|
|
import popModal from "@/views/components/popModal.vue";
|
|
|
import { getUserInfo } from "@/utils/auth";
|
|
|
import * as portraitModel from "@/api/portraitModel";
|
|
|
import { downBlobFile } from "@/utils/index.js";
|
|
|
import * as echarts from "echarts";
|
|
|
const { proxy } = getCurrentInstance();
|
|
|
const baseUrl = import.meta.env.VITE_APP_BASE_API;
|
|
|
const knowledgeHtml = ref(
|
|
|
`<p style="text-align: start;"><strong>前言</strong></p><p style="text-align: start;">Tableau的本质还是辅助分析、辅助工作,分析思维不可少。所以在分享Tableau技能之外,也会分享些有关分析技能的内容,统一更新入“Janie碎谈”模块中。</p><p style="text-align: start;">这篇文章是我花了好几个晚上认认真真写的,自己编造的数据,自己画的图,自己写的代码。一方面写的过程中会促使我进入更深层次的思考,边改进边学习边进步;另一方面独乐乐不如众乐乐,分享出来大家一起进步,顺便也帮我指出不足。</p><p style="text-align: start;">网上有关留存的文章很多,这篇不敢说是最全的,但最起码是较全的。由于上班加带娃,又要坚持原创,又要精细的准备每一篇干货,所以大概一周一更。如有做的不足的地方,请于后台留言,督促我改进,以分享更有价值的干货。</p><p style="text-align: start;">在这个用户为大的互联网世界中,我们一起发现更多有意思的点......</p><p style="text-align: start;"><strong>目录</strong></p><ol><li style="text-align: start;">互联网企业面临的留存问题<br></li><li style="text-align: start;">什么是留存分析<br></li><li style="text-align: start;">留存分析常用口径<br></li><li style="text-align: start;">留存分析的适用场景<br></li><li style="text-align: start;">留存分析参考代码<br></li><li style="text-align: start;">留存下降的可能性原因<br></li><li style="text-align: start;">留存分析方法<br></li><li style="text-align: start;">案例实攻</li></ol><p style="text-align: start;"><em><strong>1 互联网企业面临的留存问题</strong></em></p><ul><li style="text-align: start;">流量红利见顶、拉新成本高<br></li></ul><p style="text-align: start;">在极易同质化的今天,流量竞争着实激烈,提高用户留存的重要性不言而喻,且存量用户的获客成本远远低于拉新成本。</p><ul><li style="text-align: start;">新用户较易流失<br></li></ul><p style="text-align: start;">企业大规模投广告、做活动,高额支出锁不住新用户,长期可持续发展有些无力,只顾眼前利益治标不治本。</p><p style="text-align: start;"><em><strong>2 什么是留存分析</strong></em></p><p style="text-align: start;">留存率:某日用户数在第N日仍启动该App的用户比例,留存分析即分析用户随时间变化的活跃情况。获取用户只是第一步,留住用户才是所有产品最终目标。</p><p style="text-align: start;">可以理解为:由初期的摇摆用户转化为忠诚&稳定用户的过程。留存率越高,说明用户对产品越有强烈的依赖感。</p><p style="text-align: start;">可分为三个阶段:</p><ul><li style="text-align: start;">初期:新用户刚注册,用户留存下降较快,需快速让用户感受到产品核心价值。<br></li><li style="text-align: start;">中期:新用户沉淀下来,形成活跃用户。此时需分析活跃留存,加强核心功能,培养用户对产品的使用习惯。<br></li><li style="text-align: start;">后期:思考产品核心价值,做好产品迭代与优化。<br></li></ul><p style="text-align: start;">从时间维度划分:</p><p style="text-align: start;">常见的的有:次日留存、3日留存、7日留存、30日留存、周留存、月留存</p><p style="text-align: start;">从用户维度划分:</p><p style="text-align: start;">常见的的有:新用户留存、活跃留存</p><p style="text-align: start;">图解如下:</p><p style="text-align: start;"><img src="https://pic1.zhimg.com/80/v2-5f091e25d930f0fe283fd7959f4f10f0_720w.webp" alt="" data-href="" style="width: 690px;height: auto;"></p><p style="text-align: start;"><em><strong>3 留存分析常用口径</strong></em></p><p style="text-align: start;"><strong>以新用户留存为例</strong></p><p style="text-align: start;">次日留存率=(某日新增的用户中,在注册的第2天还进行登录的用户数)/ 该日新增用户数</p><p style="text-align: start;">3日留存率=(某日新增用户中,在注册的第3天还进行登录的用户数)/ 该日新增用户数</p><p style="text-align: start;">7日留存率=(某日新增的用户中,在注册的第7天还进行登录的用户数)/ 该日新增用户数</p><p style="text-align: start;">30日留存率=(某日新增的用户中,在注册的第30天还进行登录的用户数)/ 该日新增用户数</p><p style="text-align: start;">1周后留存率=(某周新增的用户中,在注册的第2周还进行登录的用户数)/ 该周新增用户数</p><p style="text-align: start;">2周后留存率=(某周新增的用户中,在注册的第3周还进行登录的用户数)/ 该周新增用户数</p><p style="text-align: start;">1月后留存率=(某月新增的用户中,在注册的第2月还进行登录的用户数)/ 该月新增用户数</p><p style="text-align: start;">2月后留存率=(某月新增的用户中,在注册的第3月还进行登录的用户数)/ 该月新增用户数</p><p style="text-align: start;"><strong>以活跃留存为例</strong></p><p style="text-align: start;">次日留存率=(某日登录的用户中,在第2天还进行登录的用户数)/ 该日登录用户数</p><p style="text-align: start;">3日留存率=(某日登录用户中,在第3天还进行登录的用户数)/ 该日登录用户数</p><p style="text-align: start;">7日留存率=(某日登录的用户中,在第7天还进行登录的用户数)/ 该日登录用户数</p><p style="text-align: start;">30日留存率=(某日登录的用户中,在第30天还进行登录的用户数)/ 该日登录用户数</p><p style="text-align: start;">1周后留存率=(某周登录的用户中,在第2周还进行登录的用户数)/ 该周登录用户数</p><p style="text-align: start;">2周后留存率=(某周登录的用户中,在第3周还进行登录的用户数)/ 该周登录用户数</p><p style="text-align: start;">1月后留存率=(某月登录的用户中,在第2月还进行登录的用户数)/ 该月登录用户数</p><p style="text-align: start;">2月后留存率=(某月登录的用户中,在第3月还进行登录的用户数)/ 该月登录用户数</p><p style="text-align: start;"><em><strong>4 留存分析的适用场景</strong></em></p><p style="text-align: start;"><strong>日留存率</strong></p><ul><li style="text-align: start;">快速判断产品是否迎合市场需求,比如新手对产品的UI设计、功能设置、新手引导等的体验是否满意,是否需做调整。<br></li><li style="text-align: start;">快速判断用户粘性,比如用户是否更易受促销活动的影响等等。<br></li></ul><p style="text-align: start;"><strong>周留存率</strong></p><ul><li style="text-align: start;">判断用户忠诚度,用户此时对产品基本已有完整的体验。一整套流程体验下来,继续访问的用户可判断为潜在忠诚用户。<br></li><li style="text-align: start;">分析用户再次访问的原因,找出产品最能巩固用户的点,且参考此点以一贯之,拓展应用到更多的用户身上,促使更多的用户留下来。<br><strong>月留存率</strong></li><li style="text-align: start;">评估迭代与优化的效果。砍掉留存率低的产品功能,进行迭代优化。<br><em><strong>5 留存分析参考代码</strong></em></li></ul><p style="text-align: start;">有些互联网公司面试会出留存SQL题型,该代码仅供参考。</p><p style="text-align: start;"><img src="https://pic4.zhimg.com/80/v2-040c3d1a7ab81f97e51fa020f30d58b3_720w.webp" alt="" data-href="" style="width: 320px;height: auto;"></p><p style="text-align: start;">代码运行结果</p><p style="text-align: start;"><img src="https://pic2.zhimg.com/80/v2-128c3da6d8252fe08b8e3051375399c9_720w.webp" alt="" data-href="" style="width: 690px;height: auto;"></p><p style="text-align: start;">语法环境:SparkSql或Impala,其他环境也可以,只是个别函数会略有差别,替换个别函数即可,无需更改代码结构。</p><p style="text-align: start;">参考代码如下:</p><pre><code class="language-text"> --以a表日期作为主体
|
|
|
select
|
|
|
t.date_a
|
|
|
,t.date_b
|
|
|
,t.diff_ab
|
|
|
,count(distinct t.user) as user_num
|
|
|
from
|
|
|
(
|
|
|
--a、b两段代码一模一样,join之后取二者日期差值
|
|
|
select
|
|
|
a.login_date as date_a
|
|
|
,b.login_date as date_b
|
|
|
,a.user
|
|
|
,datediff(b.login_date,a.login_date) as diff_ab
|
|
|
from
|
|
|
(
|
|
|
--a段代码
|
|
|
SELECT
|
|
|
login_date
|
|
|
,user
|
|
|
from dwd.user_login
|
|
|
where login_date>='2021-08-01'and login_date<=date_sub(to_date(now()),1)
|
|
|
)a
|
|
|
inner join
|
|
|
(
|
|
|
--b段代码
|
|
|
SELECT
|
|
|
login_date
|
|
|
,user
|
|
|
from dwd.user_login
|
|
|
where login_date>='2021-08-01'and login_date<=date_sub(to_date(now()),1)
|
|
|
)b on a.user=b.user
|
|
|
)t
|
|
|
group by 1,2,3
|
|
|
having t.diff_ab>=0
|
|
|
</code></pre><p style="text-align: start;"><em><strong>6 留存分析下降的可能性原因</strong></em></p><p style="text-align: start;"><strong>新用户留存下降</strong></p><ul><li style="text-align: start;">新用户并未快速的感受到产品的核心价值。<br></li><li style="text-align: start;">新手引导模块体验交差<br></li><li style="text-align: start;">新用户羊毛党居多<br></li><li style="text-align: start;">界面UI设计影响使用感<br></li><li style="text-align: start;">产品功能体验较差<br></li><li style="text-align: start;">......<br></li></ul><p style="text-align: start;"><strong>老用户留存下降</strong></p><ul><li style="text-align: start;">产品迭代功能致使用户体验变差<br></li><li style="text-align: start;">产品迭代周期较长,用户丧失新鲜感<br></li><li style="text-align: start;">受竞品影响<br></li><li style="text-align: start;">未促使用户对产品形成习惯<br></li><li style="text-align: start;">连续打卡签到送红包模块优惠力度较小,无坚持意义<br></li><li style="text-align: start;">广告推送较多<br></li><li style="text-align: start;">客服服务响应较慢、服务较差<br></li><li style="text-align: start;">无关推送<br></li><li style="text-align: start;">产品bug较多<br></li><li style="text-align: start;">受促销活动影响较大<br></li><li style="text-align: start;">......<br></li></ul><p style="text-align: start;"><em><strong>7 留存分析方法</strong></em></p><p style="text-align: start;"><img src="https://pic1.zhimg.com/80/v2-b67fd271c8b3b2926c758a8f66ae05b8_720w.webp" alt="" data-href="" style="width: 690px;height: auto;"></p><p style="text-align: start;">其中产品功能分析:</p><p style="text-align: start;">目的:找出对留存最有价值的功能&最没价值的功能,便于后期迭代优化。</p><ol><li style="text-align: start;">卓越功能:建议侧重优化用户体验。<br></li><li style="text-align: start;">大众功能:重中之重,建议反思该功能的长期价值与实用性<br></li><li style="text-align: start;">小众功能:建议保留该功能,但无需过多投入精力<br></li><li style="text-align: start;">弱势功能:建议考虑是否砍掉</li><li style="text-align: start;"><img src="https://pic3.zhimg.com/80/v2-a502ccb8e619cdf3064480b31789e10a_720w.webp" alt="" data-href="" style="width: 690px;height: auto;"></li></ol><p style="text-align: start;"><br></p><p style="text-align: start;"><em><strong>8 案例实攻</strong></em></p><p style="text-align: start;"><strong>案例一</strong></p><p style="text-align: start;">该图是我在ppt上加工出来的,选取了两日来对</p><p style="text-align: start;"><img src="https://pic2.zhimg.com/80/v2-7c80d9362d8ab209f8821b6ed7097c01_720w.webp" alt="" data-href="" style="width: 690px;height: auto;"></p><p style="text-align: start;"></p><p style="text-align: start;">解析:</p><p style="text-align: start;">2021年5月1日注册的新用户在注册的第7日留存率趋向于平稳,此时留存率60%;2021年5月2日注册的新用户在注册的第7日留存率趋向于平稳,此时留存率20%;2日注册的用户稳定留存率较1日差。</p><p style="text-align: start;">改进思路:</p><p style="text-align: start;">应使得趋向于平稳时的留存率尽可能提高,即平稳的这段线尽量往上提。</p><p style="text-align: start;"><strong>案例二</strong></p><p style="text-align: start;">数据纯属个人虚构,实际分析时建议多扩展日期,该图重在解析分析方法。</p><p style="text-align: start;">该表留存率:(某新增的用户中,在第N天还进行登录的用户数)/ 该日新增用户数</p><p style="text-align: start;"><img src="https://pic4.zhimg.com/80/v2-cd86bee54ea2171bc0af55d9c36039d7_720w.webp" alt="" data-href="" style="width: 690px;height: auto;"></p><p style="text-align: start;"><br></p><p style="text-align: start;">以8月1日的新增用户留存为例</p><p style="text-align: start;"><img src="https://pic4.zhimg.com/80/v2-7d96d0ddb94009b1ee6efaeb7ec25e03_720w.webp" alt="" data-href="" style="width: 690px;height: auto;"></p><p style="text-align: start;"><br></p><ul><li style="text-align: start;">新手探索期:单纯靠大额优惠吸引的用户会之间流失,产品价值未达到用户预期。<br></li><li style="text-align: start;">习惯养成期:产品功能&实用性未促使用户养成使用习惯。<br></li><li style="text-align: start;">活跃用户期:真正留下来的忠实用户。<br></li></ul><p style="text-align: start;">解析:</p><ol><li style="text-align: start;">新用户次留骤减60%:没有使得用户迅速发现产品价值<br></li><li style="text-align: start;">整体留存率于第10日趋向于平稳,留存率稳定于11%左右:说明8月1日的新增用户中只有11%左右发展成了忠实用户。<br></li><li style="text-align: start;">3留&7留出现留存率增长现象(注意:留存率并不会呈现持续下降情况),进一步定位原因,在8月3日与8月7日是否进行了促销活动?<br></li></ol><p style="text-align: start;"><strong>案例三</strong></p><p style="text-align: start;"><img src="https://pic4.zhimg.com/80/v2-af812f398fb38f8b78290a5469c30b1f_720w.webp" alt="" data-href="" style="width: 690px;height: auto;"></p><p style="text-align: start;">解析:</p><ol><li style="text-align: start;">表格中以8月6日注册用户的次留(71%)为起始点,8月1日注册用户的7留(34%)为结束点,二者形成对角线,纵向对比数据,颜色颜色部分留存率都比较高。首先需要确认8月7日这天运营是否做了动作?比如:该日做了促销活动、或者其他特殊活动?因为8月7日正好对应的是8月6日的次留,8月5日的3留......8月1日的7留。<br></li><li style="text-align: start;">表格中8月9日的次留是20%,远低于其他日次留,且后续留存也较其他日偏低,警惕羊毛党。</li></ol>`
|
|
|
);
|
|
|
const dialogVisible = ref(false);
|
|
|
const list = ref(["-"]);
|
|
|
const dayValue = ref("");
|
|
|
const combinationValue1 = ref("");
|
|
|
const combinationValue2 = ref("");
|
|
|
const errorNum = ref(0);
|
|
|
const step1Error = ref(0);
|
|
|
const step2Error = ref(0);
|
|
|
const step3Error = ref(0);
|
|
|
const step1AnswerFlag = ref(false);
|
|
|
const step2AnswerFlag = ref(false);
|
|
|
const step3AnswerFlag = ref(false);
|
|
|
const knowledgeFlag = ref(false);
|
|
|
//时间间隔分组数-7天内
|
|
|
const sevenNum = ref(0);
|
|
|
//时间间隔分组数-15天内
|
|
|
const fiftyNum = ref(0);
|
|
|
//时间间隔分组数-30天内
|
|
|
const thirtyNumIn = ref(0);
|
|
|
//时间间隔分组数-30天以上
|
|
|
const thirtyNumOut = ref(0);
|
|
|
const step1Data = ref([
|
|
|
{
|
|
|
date: "2021/8/1",
|
|
|
addNum: "100%",
|
|
|
day2: "88%",
|
|
|
day3: "73%",
|
|
|
day4: "60%",
|
|
|
day5: "54%",
|
|
|
day6: "38%",
|
|
|
day7: "33%",
|
|
|
day8: "25%",
|
|
|
day9: "18%",
|
|
|
day10: "12%",
|
|
|
day11: "10%",
|
|
|
day12: "9%",
|
|
|
day13: "6%",
|
|
|
day14: "68",
|
|
|
},
|
|
|
{
|
|
|
date: "2021/8/2",
|
|
|
addNum: "100%",
|
|
|
day2: "85%",
|
|
|
day3: "69%",
|
|
|
day4: "56%",
|
|
|
day5: "36%",
|
|
|
day6: "32%",
|
|
|
day7: "20%",
|
|
|
day8: "18%",
|
|
|
day9: "13%",
|
|
|
day10: "10%",
|
|
|
day11: "8%",
|
|
|
day12: "7%",
|
|
|
day13: "",
|
|
|
day14: "",
|
|
|
},
|
|
|
{
|
|
|
date: "2021/8/3",
|
|
|
addNum: "100%",
|
|
|
day2: "84%",
|
|
|
day3: "74%",
|
|
|
day4: "65%",
|
|
|
day5: "54%",
|
|
|
day6: "45%",
|
|
|
day7: "31%",
|
|
|
day8: "23%",
|
|
|
day9: "15%",
|
|
|
day10: "12%",
|
|
|
day11: "10%",
|
|
|
day12: "",
|
|
|
day13: "",
|
|
|
day14: "",
|
|
|
},
|
|
|
{
|
|
|
date: "2021/8/4",
|
|
|
addNum: "100%",
|
|
|
day2: "83%",
|
|
|
day3: "68%",
|
|
|
day4: "56%",
|
|
|
day5: "50%",
|
|
|
day6: "38%",
|
|
|
day7: "23%",
|
|
|
day8: "18%",
|
|
|
day9: "12%",
|
|
|
day10: "10%",
|
|
|
day11: "",
|
|
|
day12: "",
|
|
|
day13: "",
|
|
|
day14: "",
|
|
|
},
|
|
|
{
|
|
|
date: "2021/8/5",
|
|
|
addNum: "100%",
|
|
|
day2: "85%",
|
|
|
day3: "74%",
|
|
|
day4: "64%",
|
|
|
day5: "51%",
|
|
|
day6: "41%",
|
|
|
day7: "32%",
|
|
|
day8: "24%",
|
|
|
day9: "22%",
|
|
|
day10: "",
|
|
|
day11: "",
|
|
|
day12: "",
|
|
|
day13: "",
|
|
|
day14: "",
|
|
|
},
|
|
|
{
|
|
|
date: "2021/8/6",
|
|
|
addNum: "100%",
|
|
|
day2: "87%",
|
|
|
day3: "76%",
|
|
|
day4: "67%",
|
|
|
day5: "48%",
|
|
|
day6: "35%",
|
|
|
day7: "31%",
|
|
|
day8: "20%",
|
|
|
day9: "",
|
|
|
day10: "",
|
|
|
day11: "",
|
|
|
day12: "",
|
|
|
day13: "",
|
|
|
day14: "",
|
|
|
},
|
|
|
{
|
|
|
date: "2021/8/7",
|
|
|
addNum: "100%",
|
|
|
day2: "88%",
|
|
|
day3: "79%",
|
|
|
day4: "70%",
|
|
|
day5: "49%",
|
|
|
day6: "39%",
|
|
|
day7: "26%",
|
|
|
day8: "",
|
|
|
day9: "",
|
|
|
day10: "",
|
|
|
day11: "",
|
|
|
day12: "",
|
|
|
day13: "",
|
|
|
day14: "",
|
|
|
},
|
|
|
{
|
|
|
date: "2021/8/8",
|
|
|
addNum: "100%",
|
|
|
day2: "89%",
|
|
|
day3: "72%",
|
|
|
day4: "58%",
|
|
|
day5: "36%",
|
|
|
day6: "28%",
|
|
|
day7: "",
|
|
|
day8: "",
|
|
|
day9: "",
|
|
|
day10: "",
|
|
|
day11: "",
|
|
|
day12: "",
|
|
|
day13: "",
|
|
|
day14: "",
|
|
|
},
|
|
|
{
|
|
|
date: "2021/8/9",
|
|
|
addNum: "100%",
|
|
|
day2: "82%",
|
|
|
day3: "72%",
|
|
|
day4: "64%",
|
|
|
day5: "55%",
|
|
|
day6: "",
|
|
|
day7: "",
|
|
|
day8: "",
|
|
|
day9: "",
|
|
|
day10: "",
|
|
|
day11: "",
|
|
|
day12: "",
|
|
|
day13: "",
|
|
|
day14: "",
|
|
|
},
|
|
|
{
|
|
|
date: "2021/8/10",
|
|
|
addNum: "100%",
|
|
|
day2: "83%",
|
|
|
day3: "73%",
|
|
|
day4: "65%",
|
|
|
day5: "",
|
|
|
day6: "",
|
|
|
day7: "",
|
|
|
day8: "",
|
|
|
day9: "",
|
|
|
day10: "",
|
|
|
day11: "",
|
|
|
day12: "",
|
|
|
day13: "",
|
|
|
day14: "",
|
|
|
},
|
|
|
{
|
|
|
date: "2021/8/11",
|
|
|
addNum: "100%",
|
|
|
day2: "89%",
|
|
|
day3: "74%",
|
|
|
day4: "",
|
|
|
day5: "",
|
|
|
day6: "",
|
|
|
day7: "",
|
|
|
day8: "",
|
|
|
day9: "",
|
|
|
day10: "",
|
|
|
day11: "",
|
|
|
day12: "",
|
|
|
day13: "",
|
|
|
day14: "",
|
|
|
},
|
|
|
{
|
|
|
date: "2021/8/12",
|
|
|
addNum: "100%",
|
|
|
day2: "84%",
|
|
|
day3: "",
|
|
|
day4: "",
|
|
|
day5: "",
|
|
|
day6: "",
|
|
|
day7: "",
|
|
|
day8: "",
|
|
|
day9: "",
|
|
|
day10: "",
|
|
|
day11: "",
|
|
|
day12: "",
|
|
|
day13: "",
|
|
|
day14: "",
|
|
|
},
|
|
|
{
|
|
|
date: "2021/8/13",
|
|
|
addNum: "100%",
|
|
|
day2: "",
|
|
|
day3: "",
|
|
|
day4: "",
|
|
|
day5: "",
|
|
|
day6: "",
|
|
|
day7: "",
|
|
|
day8: "",
|
|
|
day9: "",
|
|
|
day10: "",
|
|
|
day11: "",
|
|
|
day12: "",
|
|
|
day13: "",
|
|
|
day14: "",
|
|
|
},
|
|
|
{
|
|
|
date: "2021/8/14",
|
|
|
addNum: "100%",
|
|
|
day2: "",
|
|
|
day3: "",
|
|
|
day4: "",
|
|
|
day5: "",
|
|
|
day6: "",
|
|
|
day7: "",
|
|
|
day8: "",
|
|
|
day9: "",
|
|
|
day10: "",
|
|
|
day11: "",
|
|
|
day12: "",
|
|
|
day13: "",
|
|
|
day14: "",
|
|
|
},
|
|
|
]);
|
|
|
const fileTable1 = ref([
|
|
|
{
|
|
|
date: "2021/8/1",
|
|
|
addNum: "1668",
|
|
|
day2: "1472",
|
|
|
day3: "1214",
|
|
|
day4: "1002",
|
|
|
day5: "901",
|
|
|
day6: "631",
|
|
|
day7: "556",
|
|
|
day8: "417",
|
|
|
day9: "295",
|
|
|
day10: "205",
|
|
|
day11: "172",
|
|
|
day12: "145",
|
|
|
day13: "108",
|
|
|
day14: "68",
|
|
|
},
|
|
|
{
|
|
|
date: "2021/8/2",
|
|
|
addNum: "1692",
|
|
|
day2: "1435",
|
|
|
day3: "1165",
|
|
|
day4: "946",
|
|
|
day5: "607",
|
|
|
day6: "534",
|
|
|
day7: "346",
|
|
|
day8: "300",
|
|
|
day9: "214",
|
|
|
day10: "165",
|
|
|
day11: "143",
|
|
|
day12: "126",
|
|
|
day13: "91",
|
|
|
day14: "",
|
|
|
},
|
|
|
{
|
|
|
date: "2021/8/3",
|
|
|
addNum: "1669",
|
|
|
day2: "1402",
|
|
|
day3: "1232",
|
|
|
day4: "1083",
|
|
|
day5: "897",
|
|
|
day6: "756",
|
|
|
day7: "518",
|
|
|
day8: "382",
|
|
|
day9: "258",
|
|
|
day10: "199",
|
|
|
day11: "121",
|
|
|
day12: "106",
|
|
|
day13: "",
|
|
|
day14: "",
|
|
|
},
|
|
|
{
|
|
|
date: "2021/8/4",
|
|
|
addNum: "1301",
|
|
|
day2: "1077",
|
|
|
day3: "883",
|
|
|
day4: "724",
|
|
|
day5: "651",
|
|
|
day6: "494",
|
|
|
day7: "299",
|
|
|
day8: "230",
|
|
|
day9: "155",
|
|
|
day10: "133",
|
|
|
day11: "91",
|
|
|
day12: "",
|
|
|
day13: "",
|
|
|
day14: "",
|
|
|
},
|
|
|
{
|
|
|
date: "2021/8/5",
|
|
|
addNum: "2049",
|
|
|
day2: "1748",
|
|
|
day3: "1515",
|
|
|
day4: "1314",
|
|
|
day5: "1046",
|
|
|
day6: "831",
|
|
|
day7: "658",
|
|
|
day8: "498",
|
|
|
day9: "442",
|
|
|
day10: "189",
|
|
|
day11: "",
|
|
|
day12: "",
|
|
|
day13: "",
|
|
|
day14: "",
|
|
|
},
|
|
|
{
|
|
|
date: "2021/8/6",
|
|
|
addNum: "2670",
|
|
|
day2: "2312",
|
|
|
day3: "2039",
|
|
|
day4: "1799",
|
|
|
day5: "1290",
|
|
|
day6: "922",
|
|
|
day7: "828",
|
|
|
day8: "543",
|
|
|
day9: "373",
|
|
|
day10: "",
|
|
|
day11: "",
|
|
|
day12: "",
|
|
|
day13: "",
|
|
|
day14: "",
|
|
|
},
|
|
|
{
|
|
|
date: "2021/8/7",
|
|
|
addNum: "1999",
|
|
|
day2: "1765",
|
|
|
day3: "1573",
|
|
|
day4: "1401",
|
|
|
day5: "988",
|
|
|
day6: "783",
|
|
|
day7: "514",
|
|
|
day8: "356",
|
|
|
day9: "",
|
|
|
day10: "",
|
|
|
day11: "",
|
|
|
day12: "",
|
|
|
day13: "",
|
|
|
day14: "",
|
|
|
},
|
|
|
{
|
|
|
date: "2021/8/8",
|
|
|
addNum: "2099",
|
|
|
day2: "1874",
|
|
|
day3: "1515",
|
|
|
day4: "1224",
|
|
|
day5: "765",
|
|
|
day6: "578",
|
|
|
day7: "402",
|
|
|
day8: "",
|
|
|
day9: "",
|
|
|
day10: "",
|
|
|
day11: "",
|
|
|
day12: "",
|
|
|
day13: "",
|
|
|
day14: "",
|
|
|
},
|
|
|
{
|
|
|
date: "2021/8/9",
|
|
|
addNum: "2509",
|
|
|
day2: "2050",
|
|
|
day3: "1808",
|
|
|
day4: "1595",
|
|
|
day5: "1370",
|
|
|
day6: "752",
|
|
|
day7: "",
|
|
|
day8: "",
|
|
|
day9: "",
|
|
|
day10: "",
|
|
|
day11: "",
|
|
|
day12: "",
|
|
|
day13: "",
|
|
|
day14: "",
|
|
|
},
|
|
|
{
|
|
|
date: "2021/8/10",
|
|
|
addNum: "1011",
|
|
|
day2: "839",
|
|
|
day3: "740",
|
|
|
day4: "653",
|
|
|
day5: "410",
|
|
|
day6: "",
|
|
|
day7: "",
|
|
|
day8: "",
|
|
|
day9: "",
|
|
|
day10: "",
|
|
|
day11: "",
|
|
|
day12: "",
|
|
|
day13: "",
|
|
|
day14: "",
|
|
|
},
|
|
|
{
|
|
|
date: "2021/8/11",
|
|
|
addNum: "2128",
|
|
|
day2: "1894",
|
|
|
day3: "1566",
|
|
|
day4: "1214",
|
|
|
day5: "",
|
|
|
day6: "",
|
|
|
day7: "",
|
|
|
day8: "",
|
|
|
day9: "",
|
|
|
day10: "",
|
|
|
day11: "",
|
|
|
day12: "",
|
|
|
day13: "",
|
|
|
day14: "",
|
|
|
},
|
|
|
{
|
|
|
date: "2021/8/12",
|
|
|
addNum: "1366",
|
|
|
day2: "1145",
|
|
|
day3: "983",
|
|
|
day4: "",
|
|
|
day5: "",
|
|
|
day6: "",
|
|
|
day7: "",
|
|
|
day8: "",
|
|
|
day9: "",
|
|
|
day10: "",
|
|
|
day11: "",
|
|
|
day12: "",
|
|
|
day13: "",
|
|
|
day14: "",
|
|
|
},
|
|
|
{
|
|
|
date: "2021/8/13",
|
|
|
addNum: "2971",
|
|
|
day2: "2335",
|
|
|
day3: "",
|
|
|
day4: "",
|
|
|
day5: "",
|
|
|
day6: "",
|
|
|
day7: "",
|
|
|
day8: "",
|
|
|
day9: "",
|
|
|
day10: "",
|
|
|
day11: "",
|
|
|
day12: "",
|
|
|
day13: "",
|
|
|
day14: "",
|
|
|
},
|
|
|
{
|
|
|
date: "2021/8/14",
|
|
|
addNum: "2568",
|
|
|
day2: "",
|
|
|
day3: "",
|
|
|
day4: "",
|
|
|
day5: "",
|
|
|
day6: "",
|
|
|
day7: "",
|
|
|
day8: "",
|
|
|
day9: "",
|
|
|
day10: "",
|
|
|
day11: "",
|
|
|
day12: "",
|
|
|
day13: "",
|
|
|
day14: "",
|
|
|
},
|
|
|
]);
|
|
|
const step2Data = ref([
|
|
|
{
|
|
|
name: "平均数",
|
|
|
},
|
|
|
]);
|
|
|
const step3Data = ref([
|
|
|
{
|
|
|
data1: "A-B",
|
|
|
data2: "5900",
|
|
|
},
|
|
|
{
|
|
|
data1: "A-C",
|
|
|
data2: "2400",
|
|
|
},
|
|
|
{
|
|
|
data1: "A-D",
|
|
|
data2: "1100",
|
|
|
},
|
|
|
|
|
|
{
|
|
|
data1: "B-C",
|
|
|
data2: "600",
|
|
|
},
|
|
|
{
|
|
|
data1: "B-D",
|
|
|
data2: "600",
|
|
|
},
|
|
|
{
|
|
|
data1: "C-D",
|
|
|
data2: "600",
|
|
|
},
|
|
|
]);
|
|
|
const step4Data = ref([
|
|
|
{
|
|
|
name: "平均数",
|
|
|
data1: "666",
|
|
|
data2: "A",
|
|
|
data3: "189",
|
|
|
data4: "衬衫",
|
|
|
},
|
|
|
]);
|
|
|
const step5Data = ref([
|
|
|
{
|
|
|
data1: "dd003",
|
|
|
data2: "B",
|
|
|
data3: "99",
|
|
|
data4: "裤子",
|
|
|
data5: "2024-02-04",
|
|
|
data6: "1",
|
|
|
},
|
|
|
{
|
|
|
data1: "dd007",
|
|
|
data2: "D",
|
|
|
data3: "138",
|
|
|
data4: "裤子",
|
|
|
data5: "2024-02-14",
|
|
|
data6: "2",
|
|
|
},
|
|
|
{
|
|
|
data1: "dd010",
|
|
|
data2: "D",
|
|
|
data3: "150",
|
|
|
data4: "裤子",
|
|
|
data5: "2024-02-16",
|
|
|
data6: "3",
|
|
|
},
|
|
|
{
|
|
|
data1: "dd012",
|
|
|
data2: "D",
|
|
|
data3: "137",
|
|
|
data4: "裤子",
|
|
|
data5: "2024-02-20",
|
|
|
data6: "4",
|
|
|
},
|
|
|
{
|
|
|
data1: "dd017",
|
|
|
data2: "A",
|
|
|
data3: "39",
|
|
|
data4: "睡衣",
|
|
|
data5: "2024-02-24",
|
|
|
data6: "1",
|
|
|
},
|
|
|
{
|
|
|
data1: "dd015",
|
|
|
data2: "C",
|
|
|
data3: "94",
|
|
|
data4: "睡衣",
|
|
|
data5: "2024-02-23",
|
|
|
data6: "2",
|
|
|
},
|
|
|
{
|
|
|
data1: "dd019",
|
|
|
data2: "C",
|
|
|
data3: "186",
|
|
|
data4: "睡衣",
|
|
|
data5: "2024-02-28",
|
|
|
data6: "3",
|
|
|
},
|
|
|
{
|
|
|
data1: "dd008",
|
|
|
data2: "B",
|
|
|
data3: "143",
|
|
|
data4: "外套",
|
|
|
data5: "2024-02-14",
|
|
|
data6: "1",
|
|
|
},
|
|
|
{
|
|
|
data1: "dd011",
|
|
|
data2: "C",
|
|
|
data3: "191",
|
|
|
data4: "外套",
|
|
|
data5: "2024-02-16",
|
|
|
data6: "2",
|
|
|
},
|
|
|
{
|
|
|
data1: "dd018",
|
|
|
data2: "D",
|
|
|
data3: "99",
|
|
|
data4: "外套",
|
|
|
data5: "2024-02-26",
|
|
|
data6: "3",
|
|
|
},
|
|
|
{
|
|
|
data1: "dd005",
|
|
|
data2: "F",
|
|
|
data3: "111",
|
|
|
data4: "外套",
|
|
|
data5: "2024-02-10",
|
|
|
data6: "4",
|
|
|
},
|
|
|
{
|
|
|
data1: "dd001",
|
|
|
data2: "A",
|
|
|
data3: "189",
|
|
|
data4: "衬衫",
|
|
|
data5: "2024-02-02",
|
|
|
data6: "1",
|
|
|
},
|
|
|
{
|
|
|
data1: "dd013",
|
|
|
data2: "B",
|
|
|
data3: "59",
|
|
|
data4: "衬衫",
|
|
|
data5: "2024-02-22",
|
|
|
data6: "2",
|
|
|
},
|
|
|
{
|
|
|
data1: "dd014",
|
|
|
data2: "D",
|
|
|
data3: "173",
|
|
|
data4: "衬衫",
|
|
|
data5: "2024-02-22",
|
|
|
data6: "3",
|
|
|
},
|
|
|
{
|
|
|
data1: "dd002",
|
|
|
data2: "E",
|
|
|
data3: "101",
|
|
|
data4: "短袖",
|
|
|
data5: "2024-02-02",
|
|
|
data6: "1",
|
|
|
},
|
|
|
{
|
|
|
data1: "dd020",
|
|
|
data2: "J",
|
|
|
data3: "52",
|
|
|
data4: "短袖",
|
|
|
data5: "2024-02-28",
|
|
|
data6: "2",
|
|
|
},
|
|
|
{
|
|
|
data1: "dd016",
|
|
|
data2: "K",
|
|
|
data3: "82",
|
|
|
data4: "短袖",
|
|
|
data5: "2024-02-24",
|
|
|
data6: "3",
|
|
|
},
|
|
|
{
|
|
|
data1: "dd009",
|
|
|
data2: "G",
|
|
|
data3: "171",
|
|
|
data4: "帽子",
|
|
|
data5: "2024-02-15",
|
|
|
data6: "1",
|
|
|
},
|
|
|
{
|
|
|
data1: "dd006",
|
|
|
data2: "C",
|
|
|
data3: "141",
|
|
|
data4: "皮鞋",
|
|
|
data5: "2024-02-12",
|
|
|
data6: "1",
|
|
|
},
|
|
|
{
|
|
|
data1: "dd004",
|
|
|
data2: "H",
|
|
|
data3: "176",
|
|
|
data4: "内衣",
|
|
|
data5: "2024-02-07",
|
|
|
data6: "1",
|
|
|
},
|
|
|
]);
|
|
|
const step6Data = ref([
|
|
|
{
|
|
|
data1: "1",
|
|
|
data2: "小明",
|
|
|
data3: "4",
|
|
|
data4: "2",
|
|
|
data5: "4",
|
|
|
},
|
|
|
{
|
|
|
data1: "2",
|
|
|
data2: "小红",
|
|
|
data3: "5",
|
|
|
data4: "2",
|
|
|
data5: "2",
|
|
|
},
|
|
|
{
|
|
|
data1: "3",
|
|
|
data2: "小李",
|
|
|
data3: "5",
|
|
|
data4: "1",
|
|
|
data5: "1",
|
|
|
},
|
|
|
]);
|
|
|
const rulesTable = ref([
|
|
|
{
|
|
|
data1: "1.重要价值用户",
|
|
|
data2: "高",
|
|
|
data3: "高",
|
|
|
data4: "高",
|
|
|
},
|
|
|
{
|
|
|
data1: "2.重要发展用户",
|
|
|
data2: "高",
|
|
|
data3: "低",
|
|
|
data4: "高",
|
|
|
},
|
|
|
{
|
|
|
data1: "3.重要保持用户",
|
|
|
data2: "低",
|
|
|
data3: "高",
|
|
|
data4: "高",
|
|
|
},
|
|
|
{
|
|
|
data1: "4.重要挽留用户",
|
|
|
data2: "低",
|
|
|
data3: "低",
|
|
|
data4: "高",
|
|
|
},
|
|
|
{
|
|
|
data1: "5.一般价值用户",
|
|
|
data2: "高",
|
|
|
data3: "高",
|
|
|
data4: "低",
|
|
|
},
|
|
|
{
|
|
|
data1: "6.一般发展用户",
|
|
|
data2: "高",
|
|
|
data3: "低",
|
|
|
data4: "低",
|
|
|
},
|
|
|
{
|
|
|
data1: "7.一般保持用户",
|
|
|
data2: "低",
|
|
|
data3: "高",
|
|
|
data4: "低",
|
|
|
},
|
|
|
{
|
|
|
data1: "6.一般挽留用户",
|
|
|
data2: "低",
|
|
|
data3: "低",
|
|
|
data4: "低",
|
|
|
},
|
|
|
]);
|
|
|
const typeData = ref([
|
|
|
{
|
|
|
data1: "A类商品",
|
|
|
data2: "占总销售额的80%,需要重点关注",
|
|
|
},
|
|
|
{
|
|
|
data1: "B类商品",
|
|
|
data2: "占总销售额的10%,给予次要关注",
|
|
|
},
|
|
|
{
|
|
|
data1: "C类商品",
|
|
|
data2: "占总销售额的10%,给予一般关注",
|
|
|
},
|
|
|
]);
|
|
|
const dayOptions = ref([
|
|
|
{
|
|
|
value: "1日",
|
|
|
label: "1日",
|
|
|
},
|
|
|
{
|
|
|
value: "2日",
|
|
|
label: "2日",
|
|
|
},
|
|
|
{
|
|
|
value: "3日",
|
|
|
label: "3日",
|
|
|
},
|
|
|
{
|
|
|
value: "4日",
|
|
|
label: "4日",
|
|
|
},
|
|
|
{
|
|
|
value: "5日",
|
|
|
label: "5日",
|
|
|
},
|
|
|
{
|
|
|
value: "6日",
|
|
|
label: "6日",
|
|
|
},
|
|
|
{
|
|
|
value: "7日",
|
|
|
label: "7日",
|
|
|
},
|
|
|
{
|
|
|
value: "8日",
|
|
|
label: "8日",
|
|
|
},
|
|
|
{
|
|
|
value: "9日",
|
|
|
label: "9日",
|
|
|
},
|
|
|
|
|
|
{
|
|
|
value: "10日",
|
|
|
label: "10日",
|
|
|
},
|
|
|
{
|
|
|
value: "11日",
|
|
|
label: "11日",
|
|
|
},
|
|
|
{
|
|
|
value: "12日",
|
|
|
label: "12日",
|
|
|
},
|
|
|
{
|
|
|
value: "13日",
|
|
|
label: "13日",
|
|
|
},
|
|
|
{
|
|
|
value: "14日",
|
|
|
label: "14日",
|
|
|
},
|
|
|
]);
|
|
|
const step1RightAnswer = ref([
|
|
|
"4",
|
|
|
"5",
|
|
|
"6",
|
|
|
"7",
|
|
|
"9",
|
|
|
"14",
|
|
|
"18",
|
|
|
"19",
|
|
|
"30",
|
|
|
"41",
|
|
|
"57",
|
|
|
"72",
|
|
|
"79",
|
|
|
]);
|
|
|
onMounted(() => {
|
|
|
getData();
|
|
|
});
|
|
|
onBeforeUnmount(() => {
|
|
|
saveData();
|
|
|
});
|
|
|
const moveUp = (index, row) => {
|
|
|
console.log("上移", index, row);
|
|
|
if (index > 0) {
|
|
|
const upDate = step2Data.value[index - 1];
|
|
|
step2Data.value.splice(index - 1, 1);
|
|
|
step2Data.value.splice(index, 0, upDate);
|
|
|
} else {
|
|
|
alert("已经是第一条,不可上移");
|
|
|
}
|
|
|
};
|
|
|
const moveDown = (index, row) => {
|
|
|
console.log("下移", index, row);
|
|
|
if (index + 1 === step2Data.value.length) {
|
|
|
alert("已经是最后一条,不可下移");
|
|
|
} else {
|
|
|
const downDate = step2Data.value[index + 1];
|
|
|
step2Data.value.splice(index + 1, 1);
|
|
|
step2Data.value.splice(index, 0, downDate);
|
|
|
}
|
|
|
};
|
|
|
const addCombination = () => {
|
|
|
if (list.value[0] == "-") {
|
|
|
list.value = [];
|
|
|
}
|
|
|
// list.value = [];
|
|
|
if (combinationValue1.value == "" || combinationValue2.vlaue == "") {
|
|
|
proxy.$modal.msgError("请选择组合");
|
|
|
return;
|
|
|
}
|
|
|
list.value.push(combinationValue1.value + "—" + combinationValue2.value);
|
|
|
};
|
|
|
const tableSpanMethod = ({ row, column, rowIndex, columnIndex }) => {
|
|
|
if (rowIndex === 0) {
|
|
|
if (columnIndex === 6) {
|
|
|
return [2, 1];
|
|
|
}
|
|
|
}
|
|
|
if (rowIndex === 0) {
|
|
|
if (columnIndex === 7) {
|
|
|
return [2, 1];
|
|
|
}
|
|
|
}
|
|
|
if (rowIndex === 2) {
|
|
|
if (columnIndex === 6) {
|
|
|
return [2, 1];
|
|
|
}
|
|
|
}
|
|
|
if (rowIndex === 2) {
|
|
|
if (columnIndex === 7) {
|
|
|
return [2, 1];
|
|
|
}
|
|
|
}
|
|
|
if (rowIndex === 4) {
|
|
|
if (columnIndex === 6) {
|
|
|
return [2, 1];
|
|
|
}
|
|
|
}
|
|
|
if (rowIndex === 4) {
|
|
|
if (columnIndex === 7) {
|
|
|
return [2, 1];
|
|
|
}
|
|
|
}
|
|
|
if (rowIndex === 6) {
|
|
|
if (columnIndex === 6) {
|
|
|
return [2, 1];
|
|
|
}
|
|
|
}
|
|
|
if (rowIndex === 6) {
|
|
|
if (columnIndex === 7) {
|
|
|
return [2, 1];
|
|
|
}
|
|
|
}
|
|
|
};
|
|
|
const handleChangeDay = (e) => {
|
|
|
console.log(e);
|
|
|
};
|
|
|
const draw = () => {
|
|
|
var chartDom = document.getElementById("echarts");
|
|
|
var myChart = echarts.init(chartDom, "dark");
|
|
|
var option;
|
|
|
|
|
|
option = {
|
|
|
title: {
|
|
|
text: "2021/8/1",
|
|
|
left: "center",
|
|
|
top: "10",
|
|
|
},
|
|
|
tooltip: {
|
|
|
trigger: "axis",
|
|
|
formatter: "{c}%",
|
|
|
},
|
|
|
xAxis: {
|
|
|
type: "category",
|
|
|
data: [
|
|
|
"1",
|
|
|
"2",
|
|
|
"3",
|
|
|
"4",
|
|
|
"5",
|
|
|
"6",
|
|
|
"7",
|
|
|
"8",
|
|
|
"9",
|
|
|
"10",
|
|
|
"11",
|
|
|
"12",
|
|
|
"13",
|
|
|
"14",
|
|
|
],
|
|
|
},
|
|
|
yAxis: {
|
|
|
type: "value",
|
|
|
axisLabel: {
|
|
|
formatter: "{value}%",
|
|
|
},
|
|
|
},
|
|
|
series: [
|
|
|
{
|
|
|
data: [100, 88, 73, 60, 54, 38, 33, 25, 18, 12, 10, 9, 6, 4],
|
|
|
type: "line",
|
|
|
},
|
|
|
],
|
|
|
};
|
|
|
|
|
|
option && myChart.setOption(option);
|
|
|
};
|
|
|
const downloadData = () => {
|
|
|
// portraitModel
|
|
|
// .downloadDataByRetain({})
|
|
|
// .then((res) => {
|
|
|
// // console.log(res,'--');
|
|
|
// const blob = new Blob([res], { type: "application/vnd.ms-excel" });
|
|
|
// downBlobFile(`案例数据-留存分析`, blob);
|
|
|
// })
|
|
|
// .catch((error) => {});
|
|
|
window.open(baseUrl + "/api/downDataByUserPortrait/analysisByRetention");
|
|
|
};
|
|
|
const step1Submit = () => {
|
|
|
// console.log(65);
|
|
|
step1Error.value = 0;
|
|
|
for (let i in step1Data.value.slice(0, step1Data.value.length - 1)) {
|
|
|
// console.log(fileTable1.value[i]);
|
|
|
if (!step1Data.value[i].params) {
|
|
|
proxy.$modal.msgError("请先完成所有填空");
|
|
|
return;
|
|
|
}
|
|
|
}
|
|
|
for (let i in step1Data.value.slice(0, step1Data.value.length - 1)) {
|
|
|
if (step1Data.value[i].params != step1RightAnswer.value[i]) {
|
|
|
step1Error.value++;
|
|
|
}
|
|
|
}
|
|
|
console.log(step1Error.value, "错误数");
|
|
|
proxy.$modal.msgSuccess("提交成功");
|
|
|
step1AnswerFlag.value = true;
|
|
|
};
|
|
|
const step2Submit = () => {
|
|
|
step2Error.value = 0;
|
|
|
if (
|
|
|
!step2Data.value[0].params1 ||
|
|
|
!step2Data.value[0].params2 ||
|
|
|
!step2Data.value[0].params3 ||
|
|
|
!step2Data.value[0].params4
|
|
|
) {
|
|
|
proxy.$modal.msgError("请先完成所有填空");
|
|
|
return;
|
|
|
}
|
|
|
if (step2Data.value[0].params1 && step2Data.value[0].params1 != "85") {
|
|
|
step2Error.value++;
|
|
|
}
|
|
|
if (step2Data.value[0].params2 && step2Data.value[0].params2 != "73") {
|
|
|
step2Error.value++;
|
|
|
}
|
|
|
if (step2Data.value[0].params3 && step2Data.value[0].params3 != "27") {
|
|
|
step2Error.value++;
|
|
|
}
|
|
|
if (step2Data.value[0].params4 && step2Data.value[0].params4 != "4") {
|
|
|
step2Error.value++;
|
|
|
}
|
|
|
console.log(step2Error.value, "错误数");
|
|
|
proxy.$modal.msgSuccess("提交成功");
|
|
|
step2AnswerFlag.value = true;
|
|
|
step4Data.value[0].data1 = step2Data.value[0].params1 + "%";
|
|
|
step4Data.value[0].data2 = step2Data.value[0].params2 + "%";
|
|
|
step4Data.value[0].data3 = step2Data.value[0].params3 + "%";
|
|
|
step4Data.value[0].data4 = step2Data.value[0].params4 + "%";
|
|
|
};
|
|
|
const step3Submit = () => {
|
|
|
// console.log(1132);
|
|
|
step3Error.value = 0;
|
|
|
if (dayValue.value == "") {
|
|
|
proxy.$modal.msgError("请先完成选择");
|
|
|
return;
|
|
|
}
|
|
|
if (dayValue.value != "10日") {
|
|
|
step3Error.value++;
|
|
|
}
|
|
|
console.log(step3Error.value, "错误数");
|
|
|
proxy.$modal.msgSuccess("提交成功");
|
|
|
step3AnswerFlag.value = true;
|
|
|
};
|
|
|
const saveData = () => {
|
|
|
const params = {
|
|
|
stepFiveA: step1Data.value[0].params,
|
|
|
stepFiveB: step1Data.value[1].params,
|
|
|
stepFiveC: step1Data.value[2].params,
|
|
|
stepFiveD: step1Data.value[3].params,
|
|
|
stepSixA: step1Data.value[4].params,
|
|
|
stepSixB: step1Data.value[5].params,
|
|
|
stepSixC: step1Data.value[6].params,
|
|
|
stepSixD: step1Data.value[7].params,
|
|
|
stepSevenA: step1Data.value[8].params,
|
|
|
stepSevenB: step1Data.value[9].params,
|
|
|
stepSevenC: step1Data.value[10].params,
|
|
|
stepSevenD: step1Data.value[11].params,
|
|
|
stepEightA: step1Data.value[12].params,
|
|
|
stepEightB: step2Data.value[0].params1,
|
|
|
stepEightC: step2Data.value[0].params2,
|
|
|
stepEightD: step2Data.value[0].params3,
|
|
|
stepNineA: step2Data.value[0].params4,
|
|
|
stepNineB: dayValue.value,
|
|
|
// stepNineC: step1Data.value[18].params,
|
|
|
// stepNineD: step1Data.value[19].params,
|
|
|
// stepTenA: step2Data.value[0].params,
|
|
|
// stepTenB: step2Data.value[1].params,
|
|
|
// stepTenC: step2Data.value[2].params,
|
|
|
// stepTenD: step4Data.value[0].params1,
|
|
|
// stepElevenA: step4Data.value[0].params2,
|
|
|
// stepOneA: step4Data.value[2].params1,
|
|
|
// stepOneB: step4Data.value[2].params2,
|
|
|
// stepOneC: step4Data.value[4].params1,
|
|
|
// stepOneD: step4Data.value[4].params2,
|
|
|
// stepTwoA: step4Data.value[6].params1,
|
|
|
// stepTwoB: step4Data.value[6].params2,
|
|
|
// stepTwoC: step5DataTable2.value[0].params,
|
|
|
// stepThreeA: step5DataTable2.value[1].params,
|
|
|
// stepThreeB: step5DataTable2.value[2].params,
|
|
|
// stepThreeC: step5DataTable2.value[3].params,
|
|
|
// stepThreeD: step5DataTable2.value[4].params,
|
|
|
// stepFourA: step5DataTable3.value[0].params1,
|
|
|
// stepFourB: step5DataTable3.value[0].params2,
|
|
|
// stepFourC: step5DataTable3.value[1].params1,
|
|
|
// stepFourD: step5DataTable3.value[1].params2,
|
|
|
// stepNewOne: step5DataTable3.value[2].params1,
|
|
|
// stepNewTwo: step5DataTable3.value[2].params2,
|
|
|
// stepNewThree: step5DataTable3.value[3].params1,
|
|
|
// stepNewFive: step5DataTable3.value[3].params2,
|
|
|
// stepNewSix: step5DataTable3.value[4].params1,
|
|
|
// stepNewEight: step5DataTable3.value[4].params2,
|
|
|
};
|
|
|
portraitModel
|
|
|
.saveData({
|
|
|
userId: JSON.parse(getUserInfo()).userId,
|
|
|
module: "留存分析",
|
|
|
...params,
|
|
|
})
|
|
|
.then((res) => {})
|
|
|
.catch((error) => {});
|
|
|
};
|
|
|
const getData = () => {
|
|
|
portraitModel
|
|
|
.getData({
|
|
|
userId: JSON.parse(getUserInfo()).userId,
|
|
|
module: "留存分析",
|
|
|
})
|
|
|
.then((res) => {
|
|
|
step1Data.value[0].params = res.data.stepFiveA;
|
|
|
step1Data.value[1].params = res.data.stepFiveB;
|
|
|
step1Data.value[2].params = res.data.stepFiveC;
|
|
|
step1Data.value[3].params = res.data.stepFiveD;
|
|
|
step1Data.value[4].params = res.data.stepSixA;
|
|
|
step1Data.value[5].params = res.data.stepSixB;
|
|
|
step1Data.value[6].params = res.data.stepSixC;
|
|
|
step1Data.value[7].params = res.data.stepSixD;
|
|
|
step1Data.value[8].params = res.data.stepSevenA;
|
|
|
step1Data.value[9].params = res.data.stepSevenB;
|
|
|
step1Data.value[10].params = res.data.stepSevenC;
|
|
|
step1Data.value[11].params = res.data.stepSevenD;
|
|
|
step1Data.value[12].params = res.data.stepEightA;
|
|
|
step2Data.value[0].params1 = res.data.stepEightB;
|
|
|
step2Data.value[0].params2 = res.data.stepEightC;
|
|
|
step2Data.value[0].params3 = res.data.stepEightD;
|
|
|
step2Data.value[0].params4 = res.data.stepNineA;
|
|
|
dayValue.value = res.data.stepNineB;
|
|
|
// step1Data.value[18].params = res.data.stepNineC;
|
|
|
// step1Data.value[19].params = res.data.stepNineD;
|
|
|
// step2Data.value[0].params = res.data.stepTenA;
|
|
|
// step2Data.value[1].params = res.data.stepTenB;
|
|
|
// step2Data.value[2].params = res.data.stepTenC;
|
|
|
// step4Data.value[0].params1 = res.data.stepTenD;
|
|
|
// step4Data.value[0].params2 = res.data.stepElevenA;
|
|
|
// step4Data.value[2].params1 = res.data.stepOneA;
|
|
|
// step4Data.value[2].params2 = res.data.stepOneB;
|
|
|
// step4Data.value[4].params1 = res.data.stepOneC;
|
|
|
// step4Data.value[4].params2 = res.data.stepOneD;
|
|
|
// step4Data.value[6].params1 = res.data.stepTwoA;
|
|
|
// step4Data.value[6].params2 = res.data.stepTwoB;
|
|
|
// step5DataTable2.value[0].params = res.data.stepTwoC;
|
|
|
// step5DataTable2.value[1].params = res.data.stepThreeA;
|
|
|
// step5DataTable2.value[2].params = res.data.stepThreeB;
|
|
|
// step5DataTable2.value[3].params = res.data.stepThreeC;
|
|
|
// step5DataTable2.value[4].params = res.data.stepThreeD;
|
|
|
// step5DataTable3.value[0].params1 = res.data.stepFourA;
|
|
|
// step5DataTable3.value[0].params2 = res.data.stepFourB;
|
|
|
// step5DataTable3.value[1].params1 = res.data.stepFourC;
|
|
|
// step5DataTable3.value[1].params2 = res.data.stepFourD;
|
|
|
// step5DataTable3.value[2].params1 = res.data.stepNewOne;
|
|
|
// step5DataTable3.value[2].params2 = res.data.stepNewTwo;
|
|
|
// step5DataTable3.value[3].params1 = res.data.stepNewThree;
|
|
|
// step5DataTable3.value[3].params2 = res.data.stepNewFive;
|
|
|
// step5DataTable3.value[4].params1 = res.data.stepNewSix;
|
|
|
// step5DataTable3.value[4].params2 = res.data.stepNewEight;
|
|
|
})
|
|
|
.catch((error) => {});
|
|
|
};
|
|
|
const submitData = () => {
|
|
|
if (
|
|
|
!step1AnswerFlag.value ||
|
|
|
!step2AnswerFlag.value ||
|
|
|
!step3AnswerFlag.value
|
|
|
) {
|
|
|
proxy.$modal.msgError("请先完成所有步骤!");
|
|
|
return;
|
|
|
}
|
|
|
errorNum.value = step1Error.value + step2Error.value + step3Error.value;
|
|
|
console.log(errorNum.value, "总错误次数");
|
|
|
portraitModel
|
|
|
.submit({
|
|
|
userId: JSON.parse(getUserInfo()).userId,
|
|
|
taskName: "留存分析",
|
|
|
numberOfErrors: errorNum.value,
|
|
|
})
|
|
|
.then((res) => {
|
|
|
proxy.$modal.msgSuccess("提交成功");
|
|
|
})
|
|
|
.catch((error) => {});
|
|
|
};
|
|
|
const retrain = () => {
|
|
|
portraitModel
|
|
|
.retrain({
|
|
|
userId: JSON.parse(getUserInfo()).userId,
|
|
|
module: "留存分析",
|
|
|
})
|
|
|
.then((res) => {
|
|
|
proxy.$modal.msgSuccess("重新实训成功");
|
|
|
|
|
|
for (let i in step1Data.value.slice(0, step1Data.value.length - 1)) {
|
|
|
step1Data.value[i].params = "";
|
|
|
}
|
|
|
for (let i in step2Data.value) {
|
|
|
step2Data.value[i].params1 = "";
|
|
|
step2Data.value[i].params2 = "";
|
|
|
step2Data.value[i].params3 = "";
|
|
|
step2Data.value[i].params4 = "";
|
|
|
}
|
|
|
dayValue.value = "";
|
|
|
})
|
|
|
.catch((error) => {});
|
|
|
};
|
|
|
defineExpose({
|
|
|
submitData,
|
|
|
retrain,
|
|
|
// practicalTraining,
|
|
|
});
|
|
|
</script>
|
|
|
|
|
|
<style scoped lang="scss">
|
|
|
.content {
|
|
|
width: 100%;
|
|
|
background: rgba(0, 29, 64, 0.5);
|
|
|
border: 1px solid #0452c6;
|
|
|
padding: 10px;
|
|
|
// opacity: 0.5;
|
|
|
a:hover {
|
|
|
text-decoration: underline;
|
|
|
}
|
|
|
.import {
|
|
|
display: flex;
|
|
|
font-size: 15px;
|
|
|
font-weight: bold;
|
|
|
width: 150px;
|
|
|
height: 50px;
|
|
|
background-image: url("@/assets/images/taskImport.png");
|
|
|
background-size: 150px 50px;
|
|
|
text-align: center;
|
|
|
align-items: center;
|
|
|
line-height: 50px;
|
|
|
cursor: pointer;
|
|
|
img {
|
|
|
margin-left: 20px;
|
|
|
margin-right: 8px;
|
|
|
}
|
|
|
}
|
|
|
.caseBack {
|
|
|
.title {
|
|
|
font-weight: bold;
|
|
|
margin-top: 10px;
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
span {
|
|
|
margin-left: 10px;
|
|
|
}
|
|
|
}
|
|
|
.download {
|
|
|
cursor: pointer;
|
|
|
margin-left: 20px;
|
|
|
color: #000;
|
|
|
padding-left: 10px;
|
|
|
font-size: 14px;
|
|
|
text-align: center;
|
|
|
line-height: 31px;
|
|
|
width: 89px;
|
|
|
height: 31px;
|
|
|
background: url("@/assets/images/downloadIcon.png");
|
|
|
}
|
|
|
.submit {
|
|
|
cursor: pointer;
|
|
|
margin-left: 20px;
|
|
|
color: #000;
|
|
|
padding-left: 10px;
|
|
|
font-size: 14px;
|
|
|
text-align: center;
|
|
|
line-height: 31px;
|
|
|
width: 99px;
|
|
|
height: 31px;
|
|
|
background: url("@/assets/images/提交任务.png");
|
|
|
}
|
|
|
.customerType {
|
|
|
padding-left: 10px;
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
width: 945px;
|
|
|
height: 26px;
|
|
|
background: #003b75;
|
|
|
border-radius: 10px;
|
|
|
border: 1px solid #0052a3;
|
|
|
font-size: 12px;
|
|
|
margin-top: 10px;
|
|
|
img {
|
|
|
margin-right: 10px;
|
|
|
}
|
|
|
}
|
|
|
.secondTitle {
|
|
|
margin-top: 10px;
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
img {
|
|
|
margin-right: 10px;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
.line {
|
|
|
width: 1400px;
|
|
|
height: 1px;
|
|
|
border: 1px solid #0452c6;
|
|
|
opacity: 0.5;
|
|
|
margin-top: 20px;
|
|
|
margin-bottom: 20px;
|
|
|
}
|
|
|
.addBtn {
|
|
|
background-color: #6af5fb;
|
|
|
color: #080138;
|
|
|
height: 31px;
|
|
|
border: 1px solid #6af5fb;
|
|
|
margin-left: 10px;
|
|
|
}
|
|
|
.comList {
|
|
|
ul {
|
|
|
text-align: center;
|
|
|
list-style-type: none;
|
|
|
border: 1px solid #7190d4;
|
|
|
border-bottom: none;
|
|
|
width: 124px;
|
|
|
padding: 0;
|
|
|
// padding: 0;
|
|
|
margin: 0;
|
|
|
p {
|
|
|
width: 122px;
|
|
|
height: 40px;
|
|
|
line-height: 40px;
|
|
|
background: #6e70f0;
|
|
|
margin: 0;
|
|
|
}
|
|
|
li {
|
|
|
padding: 0;
|
|
|
margin: 0;
|
|
|
line-height: 30px;
|
|
|
width: 122px;
|
|
|
height: 30px;
|
|
|
background: #003b75;
|
|
|
border-bottom: 1px solid #7190d4;
|
|
|
font-size: 14px;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
.draw {
|
|
|
width: 89px;
|
|
|
height: 31px;
|
|
|
background: url("@/assets/images/绘制.png");
|
|
|
text-align: center;
|
|
|
line-height: 31px;
|
|
|
color: #000;
|
|
|
font-size: 14px;
|
|
|
cursor: pointer;
|
|
|
}
|
|
|
.analysis {
|
|
|
width: 577px;
|
|
|
height: 117px;
|
|
|
background: #005b55;
|
|
|
border-radius: 10px;
|
|
|
margin-top: 20px;
|
|
|
font-size: 14px;
|
|
|
padding-left: 20px;
|
|
|
padding-top: 12px;
|
|
|
.conclusion {
|
|
|
// display: block;
|
|
|
|
|
|
margin-bottom: 10px;
|
|
|
font-size: 16px;
|
|
|
}
|
|
|
}
|
|
|
.generateBtn {
|
|
|
width: 185px;
|
|
|
height: 31px;
|
|
|
background: url("@/assets/images/生成统计.png");
|
|
|
text-align: center;
|
|
|
line-height: 31px;
|
|
|
color: #000;
|
|
|
font-size: 14px;
|
|
|
cursor: pointer;
|
|
|
}
|
|
|
}
|
|
|
::v-deep .el-table tr {
|
|
|
background-color: #002652 !important;
|
|
|
color: #fff;
|
|
|
}
|
|
|
::v-deep .el-table td {
|
|
|
padding-top: 3px;
|
|
|
padding-bottom: 3px;
|
|
|
}
|
|
|
</style>
|