You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
dianshang-qianduan/src/views/portraitModel/components/retainAnalysis.vue

1929 lines
63 KiB
Vue

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<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;">可以理解为:由初期的摇摆用户转化为忠诚&amp;稳定用户的过程。留存率越高,说明用户对产品越有强烈的依赖感。</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&gt;='2021-08-01'and login_date&lt;=date_sub(to_date(now()),1)
)a
inner join
(
--b段代码
SELECT
login_date
,user
from dwd.user_login
where login_date&gt;='2021-08-01'and login_date&lt;=date_sub(to_date(now()),1)
)b on a.user=b.user
)t
group by 1,2,3
having t.diff_ab&gt;=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;">目的:找出对留存最有价值的功能&amp;最没价值的功能,便于后期迭代优化。</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;">习惯养成期:产品功能&amp;实用性未促使用户养成使用习惯。<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留&amp;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>