diff --git a/src/assets/images/30cd120b9cc8f9666542bde19b97b5c.png b/src/assets/images/30cd120b9cc8f9666542bde19b97b5c.png new file mode 100644 index 0000000..c66929f Binary files /dev/null and b/src/assets/images/30cd120b9cc8f9666542bde19b97b5c.png differ diff --git a/src/assets/images/31f16a2a3038679a13ea6c4d143b764.png b/src/assets/images/31f16a2a3038679a13ea6c4d143b764.png new file mode 100644 index 0000000..0b58cf2 Binary files /dev/null and b/src/assets/images/31f16a2a3038679a13ea6c4d143b764.png differ diff --git a/src/assets/images/43290bff95bf223b26f2b6920b1d20e.png b/src/assets/images/43290bff95bf223b26f2b6920b1d20e.png new file mode 100644 index 0000000..c0886a6 Binary files /dev/null and b/src/assets/images/43290bff95bf223b26f2b6920b1d20e.png differ diff --git a/src/assets/images/u1366.png b/src/assets/images/u1366.png new file mode 100644 index 0000000..3de3cfe Binary files /dev/null and b/src/assets/images/u1366.png differ diff --git a/src/views/portraitModel/components/abcAnalysis.vue b/src/views/portraitModel/components/abcAnalysis.vue index 0cbac65..c64cd08 100644 --- a/src/views/portraitModel/components/abcAnalysis.vue +++ b/src/views/portraitModel/components/abcAnalysis.vue @@ -522,7 +522,7 @@ onMounted(() => { }); const initCharts = () => { var chartDom = document.getElementById("echarts"); - var myChart = echarts.init(chartDom, "dark"); + var myChart = echarts.init(chartDom); var option; option = { diff --git a/src/views/portraitModel/components/bostonAnalysis.vue b/src/views/portraitModel/components/bostonAnalysis.vue index 378d85b..e3e2a27 100644 --- a/src/views/portraitModel/components/bostonAnalysis.vue +++ b/src/views/portraitModel/components/bostonAnalysis.vue @@ -579,6 +579,7 @@ const option2 = ref({}); const drawPointNameStep4 = ref(""); const drawPointColorStep4 = ref(""); const pointInGridStep4 = ref([]); +const markCenterLineStep4 = ref([]); //第五步定义数据 const optionStep5 = ref({}); const drawPointNameStep5 = ref(""); @@ -724,6 +725,9 @@ const step3EchartInit = () => { color: drawPointColor.value, }); option.value && myChart.setOption(option.value); + var chartDom2 = document.getElementById("charts2"); + var myChart2 = echarts.init(chartDom2); + option2.value && myChart2.setOption(option2.value); // console.log(); // 所点击点的X轴坐标点所在X轴data的下标 // let xIndex = pointInGrid[0]; @@ -743,7 +747,24 @@ const step4EchartInit = () => { var chartDom = document.getElementById("charts2"); var myChart = echarts.init(chartDom); // var option; - + // 中心线 + const centerLine = [ + { + name: "y", + xAxis: 5, + }, + { + name: "x", + yAxis: 1000, + }, + ]; + // 中心点 + const centerMark = [ + { + value: "中心点", + coord: [5, 1000], + }, + ]; option2.value = { xAxis: { name: "X", @@ -801,14 +822,47 @@ const step4EchartInit = () => { // // [6, 600], // // [7, 1400], // ], - data: chart2OptionData.value, + data: chart1OptionData.value, type: "scatter", + markLine: { + silent: true, // 是否不响应鼠标事件 + precision: 2, // 精度 + lineStyle: { + type: "solid", + color: "#00aca6", + }, + label: { + color: "#00aca6", + position: "end", + formatter: "{b}", + }, + data: markCenterLineStep4.value, + }, + // 中心点 + markPoint: { + symbol: "roundRect", + symbolSize: 15, + itemStyle: { + color: "rgba(234, 85, 6, .8)", + }, + label: { + position: "top", + }, + // data: pointInGridStep4.value, + data: [ + { + value: "中心点", + coord: pointInGridStep4.value, + }, + ], + }, }, ], }; option2.value && myChart.setOption(option2.value); myChart.getZr().on("click", function (param) { + // markCenterLineStep4.value = []; if (drawPointNameStep4.value == "") { proxy.$modal.msgError("请选择要绘制的点"); return; @@ -819,6 +873,7 @@ const step4EchartInit = () => { chart2OptionData.value.splice(i, 1); } } + markCenterLineStep4.value.splice(0, 2); const pointInPixel = [param.offsetX, param.offsetY]; console.log("pointInPixel4", pointInPixel); //将偏移值转化为坐标值 @@ -834,6 +889,18 @@ const step4EchartInit = () => { name: drawPointNameStep4.value, color: drawPointColorStep4.value, }); + markCenterLineStep4.value.push( + { + name: "y", + xAxis: pointInGridStep4.value[0], + }, + { + name: "x", + yAxis: pointInGridStep4.value[1], + } + ); + console.log(markCenterLineStep4.value); + // console.log(markCenterLineStep4.value); option2.value && myChart.setOption(option2.value); }); }; diff --git a/src/views/portraitModel/components/funnelAnalysis.vue b/src/views/portraitModel/components/funnelAnalysis.vue index c052f18..df79cd2 100644 --- a/src/views/portraitModel/components/funnelAnalysis.vue +++ b/src/views/portraitModel/components/funnelAnalysis.vue @@ -17,7 +17,8 @@ 案例背景: - 漏斗分析模型已经广泛应用于流量监控、产品目标转化等日常数据运营与数据分析的工作中。比如一个电商APP,用户登录APP后,会看到广告页。点击广告页后会看到产品详情,如果用户想购买,就点击进去购物车页面,再进入支付页面,完成支付。每一步,用户都有流失的可能,因此两个步骤之间有一定的转化率。
+ 漏斗分析模型已经广泛应用于流量监控、产品目标转化等日常数据运营与数据分析的工作中。比如一个电商APP,用户登录APP后,会看到广告页。点击广告页后会看到产品详情,如果用户想购买,就点击进去购物车页面,再进入支付页面,完成支付。每一步,用户都有流失的可能,因此两个步骤之间有一定的转化率。 +
现有以下某购物APP各个流程节点的用户数据,需要用漏斗模型进行分析:
@@ -31,18 +32,12 @@ backgroundColor: '#6A7DE9!important', }" > - - - - - - - - - - - - + + + + + +
下载数据
@@ -54,10 +49,14 @@ 第一步,转化率计算 - 转化率=下一步人数/上一步人数*100%
- 流失率=1—转化率
- 总体转化率/最终转化率=该步人数/总访问量(浏览量)*100%
- 计算结果保留小数点后一位
+ 转化率=下一步人数/上一步人数*100% +
+ 流失率=1—转化率 +
+ 总体转化率/最终转化率=该步人数/总访问量(浏览量)*100% +
+ 计算结果保留小数点后一位 +
- - + @@ -142,18 +110,12 @@ 第二步,绘制漏斗图
- - 以各个页面节点的人数为统计指标,绘制漏斗图: - + 以各个页面节点的人数为统计指标,绘制漏斗图:
- + @@ -162,11 +124,7 @@
- + @@ -175,11 +133,7 @@
- + @@ -188,11 +142,7 @@
- + @@ -201,11 +151,7 @@
- + @@ -214,13 +160,7 @@
-
- 提交 -
+
提交
@@ -229,18 +169,12 @@ 第三步,结果分析 - - 基于转化率结果计算和图标分析,得出结论: - + 基于转化率结果计算和图标分析,得出结论:
流失率排第一位的: - + @@ -250,21 +184,14 @@
流失率排第二位的: - +
-

- 注:实际运用时 - ,转化率需要与不同时期比较、与竞争对手、行业平均水平比较,分析的结果相对准确些。 -

+

注:实际运用时 ,转化率需要与不同时期比较、与竞争对手、行业平均水平比较,分析的结果相对准确些。

提交
@@ -276,30 +203,34 @@ 第四步,营销运营改进
+ 针对转换率较低的环节步骤,制定改善措施: +
- 针对转换率较低的环节步骤,制定改善措施:
- - 一、简化购物流程
- 购物车转化率受到购物流程的影响。如果购物流程复杂或繁琐,消费者可能会因为不方便而放弃购买。因此,简化购物流程是提高购物车转化率的关键。
- 1. - 减少步骤:尽量减少购买过程中的步骤和页面数量。消费者希望能够快速完成购买,如果购买过程过于复杂,他们可能会选择放弃。
- 2. - 简化表单:简化购买表单,只收集必要的信息。过多的信息收集可能会让消费者感到烦扰,从而影响购买意愿。

+ 一、简化购物流程 +
+ 购物车转化率受到购物流程的影响。如果购物流程复杂或繁琐,消费者可能会因为不方便而放弃购买。因此,简化购物流程是提高购物车转化率的关键。 +
+ 1. 减少步骤:尽量减少购买过程中的步骤和页面数量。消费者希望能够快速完成购买,如果购买过程过于复杂,他们可能会选择放弃。 +
+ 2. 简化表单:简化购买表单,只收集必要的信息。过多的信息收集可能会让消费者感到烦扰,从而影响购买意愿。 + +
- 二、优化产品页面
- 产品页面是消费者了解和选择产品的关键环节。优化产品页面可以提高购物车转化率。
- 1. - 清晰的产品信息:确保产品页面上提供清晰、详细的产品信息,包括产品描述、规格、图片等。消费者需要充分了解产品才能做出购买决策。
- 2. - 强调产品优势和价值:突出产品的独特卖点和优势,让消费者明白购买该产品的价值和好处。
- 3. - 用户评价和评级:展示其他消费者的评价和评级可以增加消费者对产品的信任度和购买意愿。
- 4. - 清晰的购买按钮:在产品页面上放置清晰、醒目的购买按钮,方便消费者快速添加产品到购物车。
- 比如下决心改进广告页,更换了素材,更换了页面布局,最后有了ABC版本,这时候可以观察每个版本效果。如下图,持续改进广告页以后,能看到广告页点击有了提升,最终转化率也提升了。

+ 二、优化产品页面 +
+ 产品页面是消费者了解和选择产品的关键环节。优化产品页面可以提高购物车转化率。 +
+ 1. 清晰的产品信息:确保产品页面上提供清晰、详细的产品信息,包括产品描述、规格、图片等。消费者需要充分了解产品才能做出购买决策。 +
+ 2. 强调产品优势和价值:突出产品的独特卖点和优势,让消费者明白购买该产品的价值和好处。 +
+ 3. 用户评价和评级:展示其他消费者的评价和评级可以增加消费者对产品的信任度和购买意愿。 +
+ 4. 清晰的购买按钮:在产品页面上放置清晰、醒目的购买按钮,方便消费者快速添加产品到购物车。 +
+ 比如下决心改进广告页,更换了素材,更换了页面布局,最后有了ABC版本,这时候可以观察每个版本效果。如下图,持续改进广告页以后,能看到广告页点击有了提升,最终转化率也提升了。 + +
@@ -325,6 +256,7 @@ import * as echarts from "echarts"; import { downBlobFile } from "@/utils/index.js"; import { onMounted } from "vue"; const { proxy } = getCurrentInstance(); +const funnelData = ref([223, 235, 284, 622, 2071]); const dialogVisible = ref(false); const step2Select1 = ref(""); const step2Select2 = ref(""); @@ -596,10 +528,10 @@ const typeData = ref([ // }, // ], // }; -const option = { +const option = ref({ title: { - text: '漏斗图', - textStyle: { + text: "漏斗图", + textStyle: { color: "#fff", }, }, @@ -610,80 +542,67 @@ const option = { // } }, legend: { - data:[], + data: [], textStyle: { color: "#fff", }, }, grid: { - left: '3%', - right: '4%', - bottom: '3%', - containLabel: true + left: "3%", + right: "4%", + bottom: "3%", + containLabel: true, }, xAxis: { - show:false + show: false, // type: 'value', // boundaryGap: [0, 0.01] }, yAxis: { - type: 'category', - data: ['', '', '', '', ''], - position: 'center' + type: "category", + data: ["", "", "", "", ""], + position: "center", }, series: [ { - name: '', - stack: 'one', - type: 'bar', - barWidth: '60%', + name: "", + stack: "one", + type: "bar", + barWidth: "60%", data: [1120, 1113, 1090, 920, 220], itemStyle: { normal: { //这里是重点 color: function (params) { // 颜色设置透明 - var colorList = [ - 'rgba(0,0,0,0)', - 'rgba(0,0,0,0)', - 'rgba(0,0,0,0)', - 'rgba(0,0,0,0)', - 'rgba(0,0,0,0)', - 'rgba(0,0,0,0)' - ]; + var colorList = ["rgba(0,0,0,0)", "rgba(0,0,0,0)", "rgba(0,0,0,0)", "rgba(0,0,0,0)", "rgba(0,0,0,0)", "rgba(0,0,0,0)"]; return colorList[params.dataIndex]; - } - } - } + }, + }, + }, }, { - stack: 'one', - name: '', - type: 'bar', - barWidth: '60%', - - data: [223, 235, 284, 622, 2071], + stack: "one", + name: "", + type: "bar", + barWidth: "60%", + data: funnelData.value, + // data: [223, 235, 284, 622, 2071], itemStyle: { normal: { //这里是重点 color: function (params) { // 颜色设置透明 - var colorList = [ - '#009FF1', - '#003DA3', - '#00B869', - '#FE8D2A', - '#FB54A1', - ]; + var colorList = ["#009FF1", "#003DA3", "#00B869", "#FE8D2A", "#FB54A1"]; return colorList[params.dataIndex]; - } + }, }, - borderColor: "#fff", + borderColor: "#fff", borderWidth: 1, - } - } - ] -} + }, + }, + ], +}); const step1Error = ref(0); const step2Error = ref(0); const step3Error = ref(0); @@ -698,9 +617,30 @@ onBeforeUnmount(() => { onMounted(() => { getData(); var chartDom = document.getElementById("funnel"); - var myChart = echarts.init(chartDom,); - option && myChart.setOption(option); + var myChart = echarts.init(chartDom); + option.value && myChart.setOption(option.value); }); +const selectData = (item, index) => { + console.log(item, index); + if (item == "浏览2071") { + funnelData.value[index] = 2071; + } + if (item == "购物车622") { + funnelData.value[index] = 622; + } + if (item == "订单284") { + funnelData.value[index] = 284; + } + if (item == "支付235") { + funnelData.value[index] = 235; + } + if (item == "完成交易223") { + funnelData.value[index] = 223; + } + var chartDom = document.getElementById("funnel"); + var myChart = echarts.init(chartDom); + option.value && myChart.setOption(option.value); +}; const moveUp = (index, row) => { console.log("上移", index, row); if (index > 0) { @@ -726,13 +666,7 @@ const step1Submit = () => { step1Error.value = 0; const step1DataSlice = step1Data.value.slice(1); for (let i in step1DataSlice) { - if ( - !step1DataSlice[i].params1 || - !step1DataSlice[i].params2 || - !step1DataSlice[i].params3 || - !step1DataSlice[i].params4 || - !step1DataSlice[i].params5 - ) { + if (!step1DataSlice[i].params1 || !step1DataSlice[i].params2 || !step1DataSlice[i].params3 || !step1DataSlice[i].params4 || !step1DataSlice[i].params5) { proxy.$modal.msgError("请先完成所有填空"); return; } @@ -741,11 +675,7 @@ const step1Submit = () => { if (step1DataSlice[0].params1 && step1DataSlice[0].params1 !== "100") { step1Error.value++; } - if ( - step1DataSlice[0].params2 && - step1DataSlice[0].params2 !== "30.0" && - step1DataSlice[0].params2 !== "30" - ) { + if (step1DataSlice[0].params2 && step1DataSlice[0].params2 !== "30.0" && step1DataSlice[0].params2 !== "30") { step1Error.value++; } if (step1DataSlice[0].params3 && step1DataSlice[0].params3 !== "45.7") { @@ -775,11 +705,7 @@ const step1Submit = () => { if (step1DataSlice[2].params1 && step1DataSlice[2].params1 !== "100") { step1Error.value++; } - if ( - step1DataSlice[2].params2 && - step1DataSlice[2].params2 !== "30.0" && - step1DataSlice[2].params2 !== "30" - ) { + if (step1DataSlice[2].params2 && step1DataSlice[2].params2 !== "30.0" && step1DataSlice[2].params2 !== "30") { step1Error.value++; } if (step1DataSlice[2].params3 && step1DataSlice[2].params3 !== "13.7") { @@ -798,13 +724,7 @@ const step1Submit = () => { }; const step2Submit = () => { step2Error.value = 0; - if ( - step2Select1.value == "" || - step2Select2.value == "" || - step2Select3.value == "" || - step2Select4.value == "" || - step2Select5.value == "" - ) { + if (step2Select1.value == "" || step2Select2.value == "" || step2Select3.value == "" || step2Select4.value == "" || step2Select5.value == "") { proxy.$modal.msgError("请先完成选择"); return; } @@ -852,7 +772,7 @@ const downloadData = () => { // downBlobFile(`案例数据-漏斗模型`, blob); // }) // .catch((error) => {}); - window.open(baseUrl + "/api/downDataByUserPortrait/analysisByFunnelModel"); + window.open(baseUrl + "/api/downDataByUserPortrait/analysisByFunnelModel"); }; const saveData = () => { const params = { @@ -957,11 +877,7 @@ const getData = () => { .catch((error) => {}); }; const submitData = () => { - if ( - !step1AnswerFlag.value || - !step2AnswerFlag.value || - !step3AnswerFlag.value - ) { + if (!step1AnswerFlag.value || !step2AnswerFlag.value || !step3AnswerFlag.value) { proxy.$modal.msgError("请先完成所有步骤!"); return; } @@ -1038,7 +954,7 @@ defineExpose({ } } .caseBack { - color:#000; + color: #000; .title { font-weight: bold; margin-top: 10px; diff --git a/src/views/portraitModel/components/repurchaseAnalysis.vue b/src/views/portraitModel/components/repurchaseAnalysis.vue index 7541f1a..1aaaab7 100644 --- a/src/views/portraitModel/components/repurchaseAnalysis.vue +++ b/src/views/portraitModel/components/repurchaseAnalysis.vue @@ -41,9 +41,7 @@ 案例背景: - - 某购物网站2024年2月份有如下订单数据,需要复购的角度展开分析。 - + 某购物网站2024年2月份有如下订单数据,需要复购的角度展开分析。
- - - - - - - - - - + + + + +
下载数据
@@ -76,10 +69,11 @@ 第一步,区分首购订单 or 复购订单 - 我们需要根据用户ID、订单ID和购买日期,区分每行数据订单是首购or - 复购第几次。
+ 我们需要根据用户ID、订单ID和购买日期,区分每行数据订单是首购or 复购第几次。 +
- 通常采用的方法是用户ID作为主排序字段,购买日期作为第二排序字段,分类汇总次数。
+ 通常采用的方法是用户ID作为主排序字段,购买日期作为第二排序字段,分类汇总次数。 +
首购订单记为1,复购订单依次累加
@@ -93,39 +87,15 @@ backgroundColor: '#6A7DE9!important', }" > - - - - - - - - - - - + + + + + +