修复bug

fix/non-blocking-route-navigation
qinzhenpen 2 years ago
commit 7223186619

Binary file not shown.

After

Width:  |  Height:  |  Size: 146 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 217 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 143 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 631 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 416 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

@ -0,0 +1,314 @@
<template>
<div class="app-containere">
<div class="material">
<div class="title">
<img src="@/assets/images/caseIcon.png" alt="" />
<span>任务素材</span>
</div>
<div style="font-size: 15px; line-height: 30px; margin-top: 10px; margin-bottom: 10px">
根据概要文字描述提示,进行详细描述扩展。利用推荐的三个AI工具,分别生成图片。
<br />
1、风景画创作图片。文字描述:"夏日傍晚,(xxxxxx)。湖边有(xxxxxx)。远处是(xxxxxx),天空中(xxxxxx)。"
<br />
2、未来城市构想图片。文字描述:"一个高科技的未来城市,有着(xxxxxx)。城市中心(xxxxxx)。空中(xxxxxx)。夜晚(xxxxxx)。"
<br />
3、幻想生物插画。文字描述:"一只神秘的幻想生物,它有着(xxxxxx)。站在(xxxxxx),周边(xxxxxx)。
</div>
</div>
<div class="material">
<div class="title">
<img src="@/assets/images/步骤.png" alt="" />
<span>任务提交</span>
<span style="font-size: 13px">(请按照任务素材顺序依次提交)</span>
</div>
<div style="margin-top: 10px; width: 200px">
<el-upload ref="uploadRef" class="upload-demo" :file-list="previewFile1" :auto-upload="false" :on-change="handleChange1" :show-file-list="true" :limit="1">
<el-button type="primary" class="uploadBtn">+任务提交1</el-button>
</el-upload>
</div>
<div style="margin-top: 10px; width: 200px">
<el-upload ref="uploadRef" class="upload-demo" :file-list="previewFile2" :auto-upload="false" :on-change="handleChange2" :show-file-list="true" :limit="1">
<el-button type="primary" class="uploadBtn">+任务提交2</el-button>
</el-upload>
</div>
<div style="margin-top: 10px; width: 200px">
<el-upload ref="uploadRef" class="upload-demo" :file-list="previewFile3" :auto-upload="false" :on-change="handleChange3" :show-file-list="true" :limit="1">
<el-button type="primary" class="uploadBtn">+任务提交3</el-button>
</el-upload>
</div>
</div>
<div class="material" style="margin-top: 20px">
<div class="title">
<img src="@/assets/icons/svg/sxbg.svg" style="width: 30px; height: 30px" />
<span>大模型参考工具</span>
</div>
<div style="display: flex">
<div class="case">
<div class="bgItem">
<img src="@/assets/images/d24cf8e976d6f9fd2695222347683d6.png" alt="" />
</div>
<div class="detail">
<div class="title">Stable Diffusion</div>
<el-tooltip
popper-class="tooltip"
effect="light"
content="Stable Difusion 是于2022年发布的一个基于深度学习的A1文本到图像生成模型,该模型主要用于生成以文本描述为条件的详细图像和插画,由初创公司StabilityAl与一些学术研究人员和非营利组织合作开发的。
"
placement="top-start"
>
<div style="line-height: 24px; font-size: 13px">Stable Difusion 是于2022年发布的一个基于深度学习的A1文本到图像生成模型,该模型主要用于生成以文本描述为条件的详细图像和插画,由初创公司StabilityAl与一些学术研究人员和非营利组织合作开发的。</div>
</el-tooltip>
<a class="btn" href="https://stabledifffusion.com/" target="_blank">
<span>访问官网</span>
</a>
</div>
</div>
<div class="case">
<div class="bgItem">
<img src="@/assets/images/4ef9378778f4cc503f2a8c24c0858ba.png" alt="" />
</div>
<div class="detail">
<div class="title">文心一格</div>
<el-tooltip popper-class="tooltip" effect="light" content="文心一格是由百度推出的依托其文心大模型和飞桨技术的文本生成图片的 A| 艺术和创意辅助平台,于2022年8月正式发布。作为国内第一梯队的A|图片生成的工具和平台,文心一格可以进行国风、油画、水彩、水粉、动漫、写实等十余种不同风格高清画作的生成。" placement="top-start">
<div style="line-height: 24px; font-size: 13px">文心一格是由百度推出的依托其文心大模型和飞桨技术的文本生成图片的 A| 艺术和创意辅助平台,于2022年8月正式发布。作为国内第一梯队的A|图片生成的工具和平台,文心一格可以进行国风、油画、水彩...</div>
</el-tooltip>
<a class="btn" href="https://yige.baidu.com/" target="_blank">
<span>访问官网</span>
</a>
</div>
</div>
<div class="case">
<div class="bgItem">
<img src="@/assets/images/664a12e0c54099bdebfc7cfb9eff809.png" alt="" />
</div>
<div class="detail">
<!-- <div class="icon">
<div class="iconItem">AI工具</div>
<span>></span>
<div class="iconItem">AI写作对话</div>
</div> -->
<div class="title">WHEE</div>
<el-tooltip popper-class="tooltip" effect="light" content="WHEE是美图基于其视觉大模型Miraclevision最新推出的AI图片和绘画创作平台,该A|图片生成工具支持多种模式的图片创作,包括文生图、图生图、风格模型训练和创作提示词库。用户仅需输入简单的文字描述,即可将创意快速变为高质量的优秀画作。" placement="top-start">
<div style="line-height: 24px; font-size: 13px">WHEE是美图基于其视觉大模型Miraclevision最新推出的AI图片和绘画创作平台,该A|图片生成工具支持多种模式的图片创作,包括文生图、图生图、风格模型训练和创作提示词库。用户仅需输入...</div>
</el-tooltip>
<a class="btn" href="https://www.whee.com/" target="_blank">
<span>访问官网</span>
</a>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup>
import popModal from "@/views/components/popModal.vue";
import { getUserInfo, getToken } from "@/utils/auth";
import * as portraitModel from "@/api/portraitModel";
import { uploadFile } 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 previewFile1 = ref([]);
const previewFile2 = ref([]);
const previewFile3 = ref([]);
const fileList1 = ref([]);
const fileList2 = ref([]);
const fileList3 = ref([]);
const handleChange1 = async (info) => {
fileList1.value = [];
fileList1.value.push(info);
let formData = new FormData();
formData.append("file", fileList1.value[0].raw);
formData.append("userId", JSON.parse(getUserInfo()).userId);
formData.append("module", "AI文生图");
formData.append("count", 1);
try {
previewFile1.value = [];
const res = await uploadFile(formData);
// registerParams.value.imgAddress = res.data;
proxy.$modal.msgSuccess("上传成功!");
previewFile1.value.push({
name: fileList1.value[0].raw.name,
});
// getMessage();
} catch (e) {
// console.log(e);
}
};
const handleChange2 = async (info) => {
fileList2.value = [];
fileList2.value.push(info);
let formData = new FormData();
formData.append("file", fileList2.value[0].raw);
formData.append("userId", JSON.parse(getUserInfo()).userId);
formData.append("module", "AI文生图");
formData.append("count", 2);
try {
previewFile2.value = [];
const res = await uploadFile(formData);
// registerParams.value.imgAddress = res.data;
proxy.$modal.msgSuccess("上传成功!");
previewFile2.value.push({
name: fileList2.value[0].raw.name,
});
// getMessage();
} catch (e) {
// console.log(e);
}
};
const handleChange3 = async (info) => {
fileList3.value = [];
fileList3.value.push(info);
let formData = new FormData();
formData.append("file", fileList3.value[0].raw);
formData.append("userId", JSON.parse(getUserInfo()).userId);
formData.append("module", "AI文生图");
formData.append("count", 3);
try {
previewFile3.value = [];
const res = await uploadFile(formData);
// registerParams.value.imgAddress = res.data;
proxy.$modal.msgSuccess("上传成功!");
previewFile3.value.push({
name: fileList3.value[0].raw.name,
});
// getMessage();
} catch (e) {
// console.log(e);
}
};
const downloadData = (name) => {
window.open(baseUrl + "/api/bigModule/download?name=" + name + "&TOKEN=Bearer " + getToken());
};
</script>
<style lang="scss" scoped>
.app-containere {
margin: 10px 4px 10px 10px;
border: 1px solid #0452c6;
// background-color: rgba(0, 0, 0, 0.5);
background: rgba(0, 29, 64, 0.5);
padding: 25px;
color: #fff;
.material {
.title {
display: flex;
align-items: center;
font-size: 18px;
span {
margin-left: 10px;
}
}
p {
font-size: 15px;
line-height: 30px;
}
.download {
cursor: pointer;
margin-left: 20px;
color: #000;
padding-left: 10px;
font-size: 14px;
text-align: center;
line-height: 26px;
width: 76px;
height: 26px;
background: url("@/assets/images/downloadIcon.png");
background-size: 76px 26px;
}
.remand {
display: flex;
align-items: center;
width: 470px;
justify-content: space-between;
}
.case {
margin-right: 18px;
padding: 10px;
padding-top: 20px;
padding-bottom: 20px;
color: #fff;
margin-top: 10px;
// width: calc(100% - 100px);
width: 500px;
// background: #fff;
// background: #002c5b;
background: #011031;
border-radius: 10px;
border: 1px solid #003e7c;
display: flex;
align-items: center;
.bgItem {
display: flex;
align-items: center;
justify-content: center;
img {
// 186px
width: 258px;
height: 134px;
border-radius: 5px;
scale: 0.8;
}
// background-color: #e6e8ed;
background-color: #002c5b;
width: 240px;
height: 170px;
// padding: 20px;
border-radius: 10px;
box-shadow: 0 30px 20px -20px rgba(0, 0, 0, 0.15);
}
.detail {
width: 300px;
margin-left: 20px;
.icon {
display: flex;
align-items: center;
span {
color: #f1404b;
}
.iconItem {
background-color: #f1404b;
color: #fff;
font-size: 12px;
padding: 2px;
border-radius: 4px;
padding-left: 4px;
padding-right: 4px;
}
}
.title {
font-size: 20px;
font-weight: bold;
margin-top: 5px;
margin-bottom: 5px;
// font-weight: bold;
}
.btn {
display: block;
background-color: #e7e6e8;
color: #333;
width: 90px;
height: 30px;
text-align: center;
line-height: 30px;
border-radius: 5px;
margin-top: 10px;
cursor: pointer;
}
.btn:hover {
background-color: #409eff;
color: #fff;
}
}
}
}
}
</style>
<style>
.tooltip {
max-width: 260px;
}
</style>

@ -0,0 +1,291 @@
<template>
<div class="app-containere">
<div class="material">
<div class="title">
<img src="@/assets/images/caseIcon.png" alt="" />
<span>任务素材</span>
</div>
<div style="font-size: 15px; line-height: 30px; margin-top: 10px; margin-bottom: 10px">
<div style="display: flex; align-items: center">
<span>根据提供的Excel表格(“customer_shopping_data.csv”),利用AI数据分析工具,通过自然语言的对话式交互,对信息进行分析。</span>
<div class="download" @click="downloadData('AI数据分析')">Excel下载</div>
</div>
1、对数据进行描述性统计分析,以表格形式展现。
<br />
2、按照性别(男、女),分别统计销售额产品排名,查看不同性别的购物偏好,以条形图进行展现。
<br />
3、按照发票日期,以每个月为统计单位,使用折线图展示销售额变化趋势。
</div>
</div>
<div class="material">
<div class="title">
<img src="@/assets/images/步骤.png" alt="" />
<span>任务提交</span>
<span style="font-size: 13px">(请按照任务素材顺序依次提交)</span>
</div>
<div style="margin-top: 10px; width: 200px">
<el-upload ref="uploadRef" class="upload-demo" :file-list="previewFile1" :auto-upload="false" :on-change="handleChange1" :show-file-list="true" :limit="1">
<el-button type="primary" class="uploadBtn">+任务提交1</el-button>
</el-upload>
</div>
<div style="margin-top: 10px; width: 200px">
<el-upload ref="uploadRef" class="upload-demo" :file-list="previewFile2" :auto-upload="false" :on-change="handleChange2" :show-file-list="true" :limit="1">
<el-button type="primary" class="uploadBtn">+任务提交2</el-button>
</el-upload>
</div>
<div style="margin-top: 10px; width: 200px">
<el-upload ref="uploadRef" class="upload-demo" :file-list="previewFile3" :auto-upload="false" :on-change="handleChange3" :show-file-list="true" :limit="1">
<el-button type="primary" class="uploadBtn">+任务提交3</el-button>
</el-upload>
</div>
</div>
<div class="material" style="margin-top: 20px">
<div class="title">
<img src="@/assets/icons/svg/sxbg.svg" style="width: 30px; height: 30px" />
<span>大模型参考工具</span>
</div>
<div style="display: flex">
<div class="case">
<div class="bgItem">
<img src="@/assets/images/aiAnalysis1.png" alt="" />
</div>
<div class="detail">
<div class="title">办公小浣能</div>
<el-tooltip
popper-class="tooltip"
effect="light"
content="办公小浣能是由商汤科技基于其`日日新SenseNov4.0`大模型能力推出的一款新型A1数据分析工具,旨在简化数据分析过程,无需编程或复杂操作即可使用。用户可以通过自然语言输入来描述他们的数据分析需求,办公小浣能能够理解并执行这些需求,自动将数据转化为有意义的分析结果和可视化图表。
"
placement="top-start"
>
<div style="line-height: 24px; font-size: 13px">办公小浣能是由商汤科技基于其`日日新SenseNov4.0`大模型能力推出的一款新型A1数据分析工具,旨在简化数据分析过程,无需编程或复杂操作即可使用。用户可以通过自然语言输入来描述他们的数据分析需求...</div>
</el-tooltip>
<a class="btn" href="https://raccoon.sensetime.com/" target="_blank">
<span>访问官网</span>
</a>
</div>
</div>
<div class="case">
<div class="bgItem">
<img src="@/assets/images/aiAnalysis2.png" alt="" />
</div>
<div class="detail">
<div class="title">百度GBl</div>
<el-tooltip popper-class="tooltip" effect="light" content="百度GBl(Global Business inteligence)是百度推出的全球商业智能平台,它结合了大模型技术,通过自然语言的对话式交互,执行数据查询与分析任务,实现“任意表,随便问”,为企业客户建立“对话即洞察”的数据分析新范式。适用于数据分析师、业务经理、市场研究人员、销售代表、产品经理、财务人员和运营专员等多种角色。" placement="top-start">
<div style="line-height: 24px; font-size: 13px">百度GBl(Global Business inteligence)是百度推出的全球商业智能平台,它结合了大模型技术,通过自然语言的对话式交互,执行数据查询与分析任务,实现“任意表,随便问”,为企业客户建立“对话即洞察”的数据分析...</div>
</el-tooltip>
<a class="btn" href="https://gbi.cloud.baidu.com/" target="_blank">
<span>访问官网</span>
</a>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup>
import popModal from "@/views/components/popModal.vue";
import { getUserInfo, getToken } from "@/utils/auth";
import * as portraitModel from "@/api/portraitModel";
import { uploadFile } 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 previewFile1 = ref([]);
const previewFile2 = ref([]);
const previewFile3 = ref([]);
const fileList1 = ref([]);
const fileList2 = ref([]);
const fileList3 = ref([]);
const handleChange1 = async (info) => {
fileList1.value = [];
fileList1.value.push(info);
let formData = new FormData();
formData.append("file", fileList1.value[0].raw);
formData.append("userId", JSON.parse(getUserInfo()).userId);
formData.append("module", "AI数据分析");
formData.append("count", 1);
try {
previewFile1.value = [];
const res = await uploadFile(formData);
// registerParams.value.imgAddress = res.data;
proxy.$modal.msgSuccess("上传成功!");
previewFile1.value.push({
name: fileList1.value[0].raw.name,
});
// getMessage();
} catch (e) {
// console.log(e);
}
};
const handleChange2 = async (info) => {
fileList2.value = [];
fileList2.value.push(info);
let formData = new FormData();
formData.append("file", fileList2.value[0].raw);
formData.append("userId", JSON.parse(getUserInfo()).userId);
formData.append("module", "AI数据分析");
formData.append("count", 2);
try {
previewFile2.value = [];
const res = await uploadFile(formData);
// registerParams.value.imgAddress = res.data;
proxy.$modal.msgSuccess("上传成功!");
previewFile2.value.push({
name: fileList2.value[0].raw.name,
});
// getMessage();
} catch (e) {
// console.log(e);
}
};
const handleChange3 = async (info) => {
fileList3.value = [];
fileList3.value.push(info);
let formData = new FormData();
formData.append("file", fileList3.value[0].raw);
formData.append("userId", JSON.parse(getUserInfo()).userId);
formData.append("module", "AI数据分析");
formData.append("count", 3);
try {
previewFile3.value = [];
const res = await uploadFile(formData);
// registerParams.value.imgAddress = res.data;
proxy.$modal.msgSuccess("上传成功!");
previewFile3.value.push({
name: fileList3.value[0].raw.name,
});
// getMessage();
} catch (e) {
// console.log(e);
}
};
const downloadData = (name) => {
window.open(baseUrl + "/api/bigModule/download?name=" + name + "&TOKEN=Bearer " + getToken());
};
</script>
<style lang="scss" scoped>
.app-containere {
margin: 10px 4px 10px 10px;
border: 1px solid #0452c6;
// background-color: rgba(0, 0, 0, 0.5);
background: rgba(0, 29, 64, 0.5);
padding: 25px;
color: #fff;
.material {
.title {
display: flex;
align-items: center;
font-size: 18px;
span {
margin-left: 10px;
}
}
p {
font-size: 15px;
line-height: 30px;
}
.download {
cursor: pointer;
margin-left: 20px;
color: #000;
padding-left: 14px;
font-size: 14px;
text-align: center;
line-height: 30px;
width: 96px;
height: 30px;
background: url("@/assets/images/downloadIcon.png");
background-size: 96px 30px;
}
.case {
margin-right: 18px;
padding: 10px;
padding-top: 20px;
padding-bottom: 20px;
color: #fff;
margin-top: 10px;
// width: calc(100% - 100px);
width: 500px;
// background: #fff;
// background: #002c5b;
background: #011031;
border-radius: 10px;
border: 1px solid #003e7c;
display: flex;
align-items: center;
.bgItem {
display: flex;
align-items: center;
justify-content: center;
img {
// 186px
width: 258px;
height: 134px;
border-radius: 5px;
scale: 0.8;
}
// background-color: #e6e8ed;
background-color: #002c5b;
width: 240px;
height: 170px;
// padding: 20px;
border-radius: 10px;
box-shadow: 0 30px 20px -20px rgba(0, 0, 0, 0.15);
}
.detail {
width: 300px;
margin-left: 20px;
.icon {
display: flex;
align-items: center;
span {
color: #f1404b;
}
.iconItem {
background-color: #f1404b;
color: #fff;
font-size: 12px;
padding: 2px;
border-radius: 4px;
padding-left: 4px;
padding-right: 4px;
}
}
.title {
font-size: 20px;
font-weight: bold;
margin-top: 5px;
margin-bottom: 5px;
// font-weight: bold;
}
.btn {
display: block;
background-color: #e7e6e8;
color: #333;
width: 90px;
height: 30px;
text-align: center;
line-height: 30px;
border-radius: 5px;
margin-top: 10px;
cursor: pointer;
}
.btn:hover {
background-color: #409eff;
color: #fff;
}
}
}
}
}
</style>
<style>
.tooltip {
max-width: 260px;
}
</style>

@ -5,16 +5,20 @@
<img src="@/assets/images/caseIcon.png" alt="" /> <img src="@/assets/images/caseIcon.png" alt="" />
<span>任务素材</span> <span>任务素材</span>
</div> </div>
<div> <div style="font-size: 15px; line-height: 30px; margin-top: 10px; margin-bottom: 10px">
<p>
根据文字描述要求,利用推荐的AI工具,进行图片修复美化。 根据文字描述要求,利用推荐的AI工具,进行图片修复美化。
<br /> <div class="remand">
1、AI消除:去除图片中的水印和文字,只保留鞋子。 <span>1、AI消除:去除图片中的水印和文字,只保留鞋子。</span>
<br /> <div class="download" @click="downloadData('AI消除')">素材1</div>
2、AI抠图:将人物照中的背景去除,抠出人物。 </div>
<br /> <div class="remand">
3、AI扩图:将金鱼图片进行尺寸扩展,或者周边扩展。 <span>2、AI抠图:将人物照中的背景去除,抠出人物。</span>
</p> <div class="download" @click="downloadData('AI抠图')">素材2</div>
</div>
<div class="remand">
<span>3、AI扩图:将金鱼图片进行尺寸扩展,或者周边扩展。</span>
<div class="download" @click="downloadData('AI扩图')">素材3</div>
</div>
</div> </div>
</div> </div>
<div class="material"> <div class="material">
@ -105,7 +109,7 @@
</template> </template>
<script setup> <script setup>
import popModal from "@/views/components/popModal.vue"; import popModal from "@/views/components/popModal.vue";
import { getUserInfo } from "@/utils/auth"; import { getUserInfo, getToken } from "@/utils/auth";
import * as portraitModel from "@/api/portraitModel"; import * as portraitModel from "@/api/portraitModel";
import { uploadFile } from "@/api/portraitModel"; import { uploadFile } from "@/api/portraitModel";
import { downBlobFile } from "@/utils/index.js"; import { downBlobFile } from "@/utils/index.js";
@ -182,6 +186,9 @@ const handleChange3 = async (info) => {
// console.log(e); // console.log(e);
} }
}; };
const downloadData = (name) => {
window.open(baseUrl + "/api/bigModule/download?name=" + name + "&TOKEN=Bearer " + getToken());
};
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@ -205,6 +212,25 @@ const handleChange3 = async (info) => {
font-size: 15px; font-size: 15px;
line-height: 30px; line-height: 30px;
} }
.download {
cursor: pointer;
margin-left: 20px;
color: #000;
padding-left: 10px;
font-size: 14px;
text-align: center;
line-height: 26px;
width: 76px;
height: 26px;
background: url("@/assets/images/downloadIcon.png");
background-size: 76px 26px;
}
.remand {
display: flex;
align-items: center;
width: 470px;
justify-content: space-between;
}
.case { .case {
margin-right: 18px; margin-right: 18px;
padding: 10px; padding: 10px;
@ -261,7 +287,8 @@ const handleChange3 = async (info) => {
} }
} }
.title { .title {
font-size: 26px; font-size: 20px;
font-weight: bold;
margin-top: 5px; margin-top: 5px;
margin-bottom: 5px; margin-bottom: 5px;
// font-weight: bold; // font-weight: bold;
@ -270,10 +297,10 @@ const handleChange3 = async (info) => {
display: block; display: block;
background-color: #e7e6e8; background-color: #e7e6e8;
color: #333; color: #333;
width: 110px; width: 90px;
height: 40px; height: 30px;
text-align: center; text-align: center;
line-height: 40px; line-height: 30px;
border-radius: 5px; border-radius: 5px;
margin-top: 10px; margin-top: 10px;
cursor: pointer; cursor: pointer;

@ -253,7 +253,8 @@ const handleChange3 = async (info) => {
} }
} }
.title { .title {
font-size: 26px; font-size: 20px;
font-weight: bold;
margin-top: 5px; margin-top: 5px;
margin-bottom: 5px; margin-bottom: 5px;
// font-weight: bold; // font-weight: bold;
@ -262,10 +263,10 @@ const handleChange3 = async (info) => {
display: block; display: block;
background-color: #e7e6e8; background-color: #e7e6e8;
color: #333; color: #333;
width: 110px; width: 90px;
height: 40px; height: 30px;
text-align: center; text-align: center;
line-height: 40px; line-height: 30px;
border-radius: 5px; border-radius: 5px;
margin-top: 10px; margin-top: 10px;
cursor: pointer; cursor: pointer;

@ -253,7 +253,8 @@ const handleChange3 = async (info) => {
} }
} }
.title { .title {
font-size: 26px; font-size: 20px;
font-weight: bold;
margin-top: 5px; margin-top: 5px;
margin-bottom: 5px; margin-bottom: 5px;
// font-weight: bold; // font-weight: bold;
@ -262,10 +263,10 @@ const handleChange3 = async (info) => {
display: block; display: block;
background-color: #e7e6e8; background-color: #e7e6e8;
color: #333; color: #333;
width: 110px; width: 90px;
height: 40px; height: 30px;
text-align: center; text-align: center;
line-height: 40px; line-height: 30px;
border-radius: 5px; border-radius: 5px;
margin-top: 10px; margin-top: 10px;
cursor: pointer; cursor: pointer;

@ -13,7 +13,7 @@
<component v-if="page" :is="page"></component> <component v-if="page" :is="page"></component>
</template> </template>
<script setup> <script setup>
const pageData = [defineAsyncComponent(() => import("./components/AIVenisonDiagram.vue")), defineAsyncComponent(() => import("./components/AIWriting.vue")), defineAsyncComponent(() => import("./components/AIPicture.vue")), defineAsyncComponent(() => import("./components/AIVideo.vue")), defineAsyncComponent(() => import("./components/thirdPartyAIGC.vue"))]; const pageData = [defineAsyncComponent(() => import("./components/AIArticleToPic.vue")), defineAsyncComponent(() => import("./components/AIPicture.vue")), defineAsyncComponent(() => import("./components/AIVideo.vue")), defineAsyncComponent(() => import("./components/AIWriting.vue")), defineAsyncComponent(() => import("./components/AIDataAnalysis.vue")), defineAsyncComponent(() => import("./components/thirdPartyAIGC.vue"))];
const page = ref(pageData[0]); const page = ref(pageData[0]);
const clickIndx = (index) => { const clickIndx = (index) => {
page.value = pageData[index]; page.value = pageData[index];
@ -23,10 +23,6 @@ const imgData = [
text: "AI文生图", text: "AI文生图",
img: "wst", img: "wst",
}, },
{
text: "AI写作",
img: "wz",
},
{ {
text: "AI修图", text: "AI修图",
img: "xt", img: "xt",
@ -35,6 +31,14 @@ const imgData = [
text: "AI视频", text: "AI视频",
img: "sp", img: "sp",
}, },
{
text: "AI写作",
img: "wz",
},
{
text: "AI数据分析",
img: "bt",
},
{ {
text: "第三方AIGC大模型", text: "第三方AIGC大模型",
img: "dmx", img: "dmx",

File diff suppressed because one or more lines are too long

@ -64,7 +64,13 @@
<el-table-column label="商品名称" align="center" prop="name"></el-table-column> <el-table-column label="商品名称" align="center" prop="name"></el-table-column>
<el-table-column label="销售额" align="center" prop="amount"> <el-table-column label="销售额" align="center" prop="amount">
<template #default="scope"> <template #default="scope">
<div style="display: flex; align-items: center; justify-content: center">
<el-input v-model="scope.row.params" placeholder="请输入" style="width: 130px"></el-input> <el-input v-model="scope.row.params" placeholder="请输入" style="width: 130px"></el-input>
<div v-if="showAnswerFlag" style="margin-left: 3px">
<span v-if="scope.row.isError" style="color: red">X</span>
<span v-if="!scope.row.isError" style="color: #00bb00">√</span>
</div>
</div>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
@ -122,17 +128,29 @@
}" }"
> >
<el-table-column label="商品名称" align="center" prop="data1"></el-table-column> <el-table-column label="商品名称" align="center" prop="data1"></el-table-column>
<el-table-column label="销售额" align="center" prop="data2"></el-table-column> <el-table-column label="销售额" align="center" prop="data2" width="100"></el-table-column>
<el-table-column label="销售额占比(%)" align="center" prop="data3"> <el-table-column label="销售额占比(%)" align="center" prop="data3">
<template #default="scope"> <template #default="scope">
<div style="display: flex; align-items: center; justify-content: center">
<el-input v-model="scope.row.params1" placeholder="请输入" style="width: 110px"></el-input> <el-input v-model="scope.row.params1" placeholder="请输入" style="width: 110px"></el-input>
% %
<div v-if="showAnswerFlag" style="margin-left: 3px">
<span v-if="scope.row.isError1" style="color: red">X</span>
<span v-if="!scope.row.isError1" style="color: #00bb00">√</span>
</div>
</div>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="累计销售额占比(%)" align="center" prop="data4"> <el-table-column label="累计销售额占比(%)" align="center" prop="data4" width="200">
<template #default="scope"> <template #default="scope">
<div style="display: flex; align-items: center; justify-content: center">
<el-input v-model="scope.row.params2" placeholder="请输入" style="width: 110px"></el-input> <el-input v-model="scope.row.params2" placeholder="请输入" style="width: 110px"></el-input>
% %
<div v-if="showAnswerFlag" style="margin-left: 3px">
<span v-if="scope.row.isError2" style="color: red">X</span>
<span v-if="!scope.row.isError2" style="color: #00bb00">√</span>
</div>
</div>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
@ -176,11 +194,17 @@
<el-table-column label="累计销售额占比(%)" align="center" prop="data3"></el-table-column> <el-table-column label="累计销售额占比(%)" align="center" prop="data3"></el-table-column>
<el-table-column label="划分商品类型" align="center" prop="data4"> <el-table-column label="划分商品类型" align="center" prop="data4">
<template #default="scope"> <template #default="scope">
<div style="display: flex; align-items: center; justify-content: center">
<el-select v-model="scope.row.params" placeholder="请选择" style="width: 100px"> <el-select v-model="scope.row.params" placeholder="请选择" style="width: 100px">
<el-option :label="'A类商品'" :value="'A类商品'" /> <el-option :label="'A类商品'" :value="'A类商品'" />
<el-option :label="'B类商品'" :value="'B类商品'" /> <el-option :label="'B类商品'" :value="'B类商品'" />
<el-option :label="'C类商品'" :value="'C类商品'" /> <el-option :label="'C类商品'" :value="'C类商品'" />
</el-select> </el-select>
<div v-if="showAnswerFlag" style="margin-left: 3px">
<span v-if="scope.row.isError" style="color: red">X</span>
<span v-if="!scope.row.isError" style="color: #00bb00">√</span>
</div>
</div>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
@ -199,30 +223,54 @@
<div class="submit" @click="step5Submit" v-if="step3AnswerFlag">提交</div> <div class="submit" @click="step5Submit" v-if="step3AnswerFlag">提交</div>
</div> </div>
<div class="chartXData" v-if="step3AnswerFlag"> <div class="chartXData" v-if="step3AnswerFlag">
<div style="display: flex; align-items: center; justify-content: center">
<el-select v-model="chartParam1" placeholder="请选择" style="width: 85px" class="XdataItem" size="small"> <el-select v-model="chartParam1" placeholder="请选择" style="width: 85px" class="XdataItem" size="small">
<el-option :label="'男士配饰'" :value="'男士配饰'" /> <el-option :label="'男士配饰'" :value="'男士配饰'" />
<el-option :label="'床上用品'" :value="'床上用品'" /> <el-option :label="'床上用品'" :value="'床上用品'" />
<el-option :label="'婴儿用品'" :value="'婴儿用品'" /> <el-option :label="'婴儿用品'" :value="'婴儿用品'" />
<el-option :label="'儿童服装'" :value="'儿童服装'" /> <el-option :label="'儿童服装'" :value="'儿童服装'" />
</el-select> </el-select>
<div v-if="showAnswerFlag">
<span v-if="chartParam1 != '男士配饰'" style="color: red">X</span>
<span v-if="chartParam1 == '男士配饰'" style="color: #00bb00">√</span>
</div>
</div>
<div style="display: flex; align-items: center; justify-content: center">
<el-select v-model="chartParam2" placeholder="请选择" style="width: 85px" class="XdataItem" size="small"> <el-select v-model="chartParam2" placeholder="请选择" style="width: 85px" class="XdataItem" size="small">
<el-option :label="'男士配饰'" :value="'男士配饰'" /> <el-option :label="'男士配饰'" :value="'男士配饰'" />
<el-option :label="'床上用品'" :value="'床上用品'" /> <el-option :label="'床上用品'" :value="'床上用品'" />
<el-option :label="'婴儿用品'" :value="'婴儿用品'" /> <el-option :label="'婴儿用品'" :value="'婴儿用品'" />
<el-option :label="'儿童服装'" :value="'儿童服装'" /> <el-option :label="'儿童服装'" :value="'儿童服装'" />
</el-select> </el-select>
<div v-if="showAnswerFlag">
<span v-if="chartParam2 != '床上用品'" style="color: red">X</span>
<span v-if="chartParam2 == '床上用品'" style="color: #00bb00">√</span>
</div>
</div>
<div style="display: flex; align-items: center; justify-content: center">
<el-select v-model="chartParam3" placeholder="请选择" style="width: 85px" class="XdataItem" size="small"> <el-select v-model="chartParam3" placeholder="请选择" style="width: 85px" class="XdataItem" size="small">
<el-option :label="'男士配饰'" :value="'男士配饰'" /> <el-option :label="'男士配饰'" :value="'男士配饰'" />
<el-option :label="'床上用品'" :value="'床上用品'" /> <el-option :label="'床上用品'" :value="'床上用品'" />
<el-option :label="'婴儿用品'" :value="'婴儿用品'" /> <el-option :label="'婴儿用品'" :value="'婴儿用品'" />
<el-option :label="'儿童服装'" :value="'儿童服装'" /> <el-option :label="'儿童服装'" :value="'儿童服装'" />
</el-select> </el-select>
<div v-if="showAnswerFlag">
<span v-if="chartParam3 != '婴儿用品'" style="color: red">X</span>
<span v-if="chartParam3 == '婴儿用品'" style="color: #00bb00">√</span>
</div>
</div>
<div style="display: flex; align-items: center; justify-content: center">
<el-select v-model="chartParam4" placeholder="请选择" style="width: 85px" class="XdataItem" size="small" @change="selectChange"> <el-select v-model="chartParam4" placeholder="请选择" style="width: 85px" class="XdataItem" size="small" @change="selectChange">
<el-option :label="'男士配饰'" :value="'男士配饰'" /> <el-option :label="'男士配饰'" :value="'男士配饰'" />
<el-option :label="'床上用品'" :value="'床上用品'" /> <el-option :label="'床上用品'" :value="'床上用品'" />
<el-option :label="'婴儿用品'" :value="'婴儿用品'" /> <el-option :label="'婴儿用品'" :value="'婴儿用品'" />
<el-option :label="'儿童服装'" :value="'儿童服装'" /> <el-option :label="'儿童服装'" :value="'儿童服装'" />
</el-select> </el-select>
<div v-if="showAnswerFlag">
<span v-if="chartParam4 != '儿童服装'" style="color: red">X</span>
<span v-if="chartParam4 == '儿童服装'" style="color: #00bb00">√</span>
</div>
</div>
</div> </div>
</div> </div>
<div class="line"></div> <div class="line"></div>
@ -280,6 +328,7 @@ import * as portraitModel from "@/api/portraitModel";
import { downBlobFile } from "@/utils/index.js"; import { downBlobFile } from "@/utils/index.js";
const { proxy } = getCurrentInstance(); const { proxy } = getCurrentInstance();
const baseUrl = import.meta.env.VITE_APP_BASE_API; const baseUrl = import.meta.env.VITE_APP_BASE_API;
const showAnswerFlag = ref(false);
const dialogVisible = ref(false); const dialogVisible = ref(false);
const knowledgeFlag = ref(false); const knowledgeFlag = ref(false);
const errorNum = ref(0); const errorNum = ref(0);
@ -522,7 +571,7 @@ onMounted(() => {
}); });
const initCharts = () => { const initCharts = () => {
var chartDom = document.getElementById("echarts"); var chartDom = document.getElementById("echarts");
var myChart = echarts.init(chartDom, "dark"); var myChart = echarts.init(chartDom);
var option; var option;
option = { option = {
@ -653,15 +702,27 @@ const step1Submit = () => {
} }
if (step1Data.value[0].params && step1Data.value[0].params !== "5900") { if (step1Data.value[0].params && step1Data.value[0].params !== "5900") {
step1Error.value++; step1Error.value++;
step1Data.value[0].isError = true;
} else {
step1Data.value[0].isError = false;
} }
if (step1Data.value[1].params && step1Data.value[1].params !== "600") { if (step1Data.value[1].params && step1Data.value[1].params !== "600") {
step1Error.value++; step1Error.value++;
step1Data.value[1].isError = true;
} else {
step1Data.value[1].isError = false;
} }
if (step1Data.value[2].params && step1Data.value[2].params !== "1100") { if (step1Data.value[2].params && step1Data.value[2].params !== "1100") {
step1Error.value++; step1Error.value++;
step1Data.value[2].isError = true;
} else {
step1Data.value[2].isError = false;
} }
if (step1Data.value[3].params && step1Data.value[3].params !== "2400") { if (step1Data.value[3].params && step1Data.value[3].params !== "2400") {
step1Error.value++; step1Error.value++;
step1Data.value[3].isError = true;
} else {
step1Data.value[3].isError = false;
} }
console.log(step1Error.value, "错误数"); console.log(step1Error.value, "错误数");
proxy.$modal.msgSuccess("提交成功"); proxy.$modal.msgSuccess("提交成功");
@ -698,27 +759,51 @@ const step3Submit = () => {
} }
if (step3Data.value[0].params1 && step3Data.value[0].params1 !== "59") { if (step3Data.value[0].params1 && step3Data.value[0].params1 !== "59") {
step3Error.value++; step3Error.value++;
step3Data.value[0].isError1 = true;
} else {
step3Data.value[0].isError1 = false;
} }
if (step3Data.value[0].params2 && step3Data.value[0].params2 !== "59") { if (step3Data.value[0].params2 && step3Data.value[0].params2 !== "59") {
step3Error.value++; step3Error.value++;
step3Data.value[0].isError2 = true;
} else {
step3Data.value[0].isError2 = false;
} }
if (step3Data.value[1].params1 && step3Data.value[1].params1 !== "24") { if (step3Data.value[1].params1 && step3Data.value[1].params1 !== "24") {
step3Error.value++; step3Error.value++;
step3Data.value[1].isError1 = true;
} else {
step3Data.value[1].isError1 = false;
} }
if (step3Data.value[1].params2 && step3Data.value[1].params2 !== "83") { if (step3Data.value[1].params2 && step3Data.value[1].params2 !== "83") {
step3Error.value++; step3Error.value++;
step3Data.value[1].isError2 = true;
} else {
step3Data.value[1].isError2 = false;
} }
if (step3Data.value[2].params1 && step3Data.value[2].params1 !== "11") { if (step3Data.value[2].params1 && step3Data.value[2].params1 !== "11") {
step3Error.value++; step3Error.value++;
step3Data.value[2].isError1 = true;
} else {
step3Data.value[2].isError1 = false;
} }
if (step3Data.value[2].params2 && step3Data.value[2].params2 !== "94") { if (step3Data.value[2].params2 && step3Data.value[2].params2 !== "94") {
step3Error.value++; step3Error.value++;
step3Data.value[2].isError2 = true;
} else {
step3Data.value[2].isError2 = false;
} }
if (step3Data.value[3].params1 && step3Data.value[3].params1 !== "6") { if (step3Data.value[3].params1 && step3Data.value[3].params1 !== "6") {
step3Error.value++; step3Error.value++;
step3Data.value[3].isError1 = true;
} else {
step3Data.value[3].isError1 = false;
} }
if (step3Data.value[3].params2 && step3Data.value[3].params2 !== "100") { if (step3Data.value[3].params2 && step3Data.value[3].params2 !== "100") {
step3Error.value++; step3Error.value++;
step3Data.value[3].isError2 = true;
} else {
step3Data.value[3].isError2 = false;
} }
console.log("错误数", step3Error.value); console.log("错误数", step3Error.value);
proxy.$modal.msgSuccess("提交成功"); proxy.$modal.msgSuccess("提交成功");
@ -745,15 +830,27 @@ const step4Submit = () => {
} }
if (step4Data.value[0].params && step4Data.value[0].params !== "A类商品") { if (step4Data.value[0].params && step4Data.value[0].params !== "A类商品") {
step4Error.value++; step4Error.value++;
step4Data.value[0].isError = true;
} else {
step4Data.value[0].isError = false;
} }
if (step4Data.value[1].params && step4Data.value[1].params !== "B类商品") { if (step4Data.value[1].params && step4Data.value[1].params !== "B类商品") {
step4Error.value++; step4Error.value++;
step4Data.value[1].isError = true;
} else {
step4Data.value[1].isError = false;
} }
if (step4Data.value[2].params && step4Data.value[2].params !== "C类商品") { if (step4Data.value[2].params && step4Data.value[2].params !== "C类商品") {
step4Error.value++; step4Error.value++;
step4Data.value[2].isError = true;
} else {
step4Data.value[2].isError = false;
} }
if (step4Data.value[3].params && step4Data.value[3].params !== "C类商品") { if (step4Data.value[3].params && step4Data.value[3].params !== "C类商品") {
step4Error.value++; step4Error.value++;
step4Data.value[3].isError = true;
} else {
step4Data.value[3].isError = false;
} }
console.log("错误数", step4Error.value); console.log("错误数", step4Error.value);
proxy.$modal.msgSuccess("提交成功"); proxy.$modal.msgSuccess("提交成功");
@ -900,9 +997,11 @@ const submitData = () => {
userId: JSON.parse(getUserInfo()).userId, userId: JSON.parse(getUserInfo()).userId,
taskName: "帕累托/ABC分析", taskName: "帕累托/ABC分析",
numberOfErrors: errorNum.value, numberOfErrors: errorNum.value,
subState: 1,
}) })
.then((res) => { .then((res) => {
proxy.$modal.msgSuccess("提交成功"); proxy.$modal.msgSuccess("提交成功");
showAnswerFlag.value = true;
}) })
.catch((error) => {}); .catch((error) => {});
}; };
@ -942,7 +1041,8 @@ defineExpose({
<style scoped lang="scss"> <style scoped lang="scss">
.content { .content {
width: 100%; width: 100%;
background: rgba(0, 29, 64, 0.5); // background: rgba(0, 29, 64, 0.5);
background: #fff;
border: 1px solid #0452c6; border: 1px solid #0452c6;
padding: 10px; padding: 10px;
// opacity: 0.5; // opacity: 0.5;
@ -965,6 +1065,7 @@ defineExpose({
} }
} }
.caseBack { .caseBack {
color: #000;
.title { .title {
font-weight: bold; font-weight: bold;
margin-top: 10px; margin-top: 10px;
@ -1004,9 +1105,10 @@ defineExpose({
align-items: center; align-items: center;
width: 945px; width: 945px;
height: 26px; height: 26px;
background: #003b75; // background: #003b75;
background: #fff8ee;
border-radius: 10px; border-radius: 10px;
border: 1px solid #0052a3; // border: 1px solid #0052a3;
font-size: 12px; font-size: 12px;
margin-top: 10px; margin-top: 10px;
img { img {
@ -1014,11 +1116,12 @@ defineExpose({
} }
} }
.chartXData { .chartXData {
display: flex;
position: relative; position: relative;
top: -58px; top: -58px;
left: 60px; left: 50px;
.XdataItem { .XdataItem {
margin-right: 15px; margin-left: 10px;
} }
} }
} }
@ -1031,9 +1134,17 @@ defineExpose({
margin-bottom: 20px; margin-bottom: 20px;
} }
} }
// ::v-deep .el-table tr {
// background-color: #002652 !important;
// color: #fff;
// }
::v-deep .el-table tr { ::v-deep .el-table tr {
background-color: #002652 !important; background-color: #fff !important;
color: #fff; color: #000;
}
/* 将悬停背景色改为红色 */
::v-deep .el-table--enable-row-hover .el-table__body tr:hover > td {
background-color: #f5f7fa !important;
} }
::v-deep .el-table td { ::v-deep .el-table td {
padding-top: 4px; padding-top: 4px;

File diff suppressed because one or more lines are too long

@ -68,12 +68,24 @@
<el-table-column label="客户ID" align="center" prop="name"></el-table-column> <el-table-column label="客户ID" align="center" prop="name"></el-table-column>
<el-table-column label="消费次数" align="center" prop="amount"> <el-table-column label="消费次数" align="center" prop="amount">
<template #default="scope"> <template #default="scope">
<div style="display: flex; align-items: center; justify-content: center">
<el-input v-model="scope.row.params1" placeholder="请输入" style="width: 130px"></el-input> <el-input v-model="scope.row.params1" placeholder="请输入" style="width: 130px"></el-input>
<div v-if="showAnswerFlag" style="margin-left: 3px">
<span v-if="scope.row.isError1" style="color: red">X</span>
<span v-if="!scope.row.isError1" style="color: #00bb00">√</span>
</div>
</div>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="消费金额" align="center" prop="amount"> <el-table-column label="消费金额" align="center" prop="amount">
<template #default="scope"> <template #default="scope">
<div style="display: flex; align-items: center; justify-content: center">
<el-input v-model="scope.row.params2" placeholder="请输入" style="width: 130px"></el-input> <el-input v-model="scope.row.params2" placeholder="请输入" style="width: 130px"></el-input>
<div v-if="showAnswerFlag" style="margin-left: 3px">
<span v-if="scope.row.isError2" style="color: red">X</span>
<span v-if="!scope.row.isError2" style="color: #00bb00">√</span>
</div>
</div>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
@ -102,11 +114,19 @@
<el-table-column label="消费次数" align="center" prop="amount"> <el-table-column label="消费次数" align="center" prop="amount">
<template #default="scope"> <template #default="scope">
<el-input v-model="scope.row.params1" placeholder="请输入" style="width: 130px" v-if="scope.$index == 4"></el-input> <el-input v-model="scope.row.params1" placeholder="请输入" style="width: 130px" v-if="scope.$index == 4"></el-input>
<div v-if="showAnswerFlag & (scope.$index == 4)" style="margin-left: 3px; display: inline-block">
<span v-if="scope.row.isError1" style="color: red">X</span>
<span v-if="!scope.row.isError1" style="color: #00bb00">√</span>
</div>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="消费金额" align="center" prop="account"> <el-table-column label="消费金额" align="center" prop="account">
<template #default="scope"> <template #default="scope">
<el-input v-model="scope.row.params2" placeholder="请输入" style="width: 130px" v-if="scope.$index == 4"></el-input> <el-input v-model="scope.row.params2" placeholder="请输入" style="width: 130px" v-if="scope.$index == 4"></el-input>
<div v-if="showAnswerFlag & (scope.$index == 4)" style="margin-left: 3px; display: inline-block">
<span v-if="scope.row.isError2" style="color: red">X</span>
<span v-if="!scope.row.isError2" style="color: #00bb00">√</span>
</div>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
@ -128,18 +148,34 @@
<div class="point"> <div class="point">
<div class="pointItem" @click="drawPoint('A', '#009FF1')">绘制A</div> <div class="pointItem" @click="drawPoint('A', '#009FF1')">绘制A</div>
<span>(3,800)</span> <span>(3,800)</span>
<div v-if="showAnswerFlag" style="margin-left: 3px; display: inline-block">
<span v-if="pointAError" style="color: red">X</span>
<span v-if="!pointAError" style="color: #00bb00">√</span>
</div>
</div> </div>
<div class="point"> <div class="point">
<div class="pointItem" @click="drawPoint('B', '#FB54A1')">绘制B</div> <div class="pointItem" @click="drawPoint('B', '#FB54A1')">绘制B</div>
<span>(4,1200)</span> <span>(4,1200)</span>
<div v-if="showAnswerFlag" style="margin-left: 3px; display: inline-block">
<span v-if="pointBError" style="color: red">X</span>
<span v-if="!pointBError" style="color: #00bb00">√</span>
</div>
</div> </div>
<div class="point"> <div class="point">
<div class="pointItem" @click="drawPoint('C', '#FE8D2A')">绘制C</div> <div class="pointItem" @click="drawPoint('C', '#FE8D2A')">绘制C</div>
<span>(6,600)</span> <span>(6,600)</span>
<div v-if="showAnswerFlag" style="margin-left: 3px; display: inline-block">
<span v-if="pointCError" style="color: red">X</span>
<span v-if="!pointCError" style="color: #00bb00">√</span>
</div>
</div> </div>
<div class="point"> <div class="point">
<div class="pointItem" @click="drawPoint('D', '#6E70F0')">绘制D</div> <div class="pointItem" @click="drawPoint('D', '#6E70F0')">绘制D</div>
<span>(7,1400)</span> <span>(7,1400)</span>
<div v-if="showAnswerFlag" style="margin-left: 3px; display: inline-block">
<span v-if="pointDError" style="color: red">X</span>
<span v-if="!pointDError" style="color: #00bb00">√</span>
</div>
</div> </div>
</div> </div>
</div> </div>
@ -160,6 +196,10 @@
<div class="point"> <div class="point">
<div class="pointItem" @click="drawPointStep4('E', '#009FF1')">绘制平均消费次数X,平均消费金额Y</div> <div class="pointItem" @click="drawPointStep4('E', '#009FF1')">绘制平均消费次数X,平均消费金额Y</div>
<span>(5,1000)</span> <span>(5,1000)</span>
<div v-if="showAnswerFlag" style="margin-left: 3px; display: inline-block">
<span v-if="centerPointError" style="color: red">X</span>
<span v-if="!centerPointError" style="color: #00bb00">√</span>
</div>
</div> </div>
<!-- <div class="point"> <!-- <div class="point">
<div class="pointItem" @click="drawPointStep4('Y', '#FB54A1')"> <div class="pointItem" @click="drawPointStep4('Y', '#FB54A1')">
@ -195,15 +235,31 @@
<div class="drawPoint"> <div class="drawPoint">
<div class="point"> <div class="point">
<div class="pointItem" @click="drawQuadrant('明星客户', 'rgba(52, 134, 207, 0.8)')">明星客户</div> <div class="pointItem" @click="drawQuadrant('明星客户', 'rgba(52, 134, 207, 0.8)')">明星客户</div>
<div v-if="showAnswerFlag" style="margin-left: 3px; display: inline-block">
<span v-if="markArea1Error" style="color: red">X</span>
<span v-if="!markArea1Error" style="color: #00bb00">√</span>
</div>
</div> </div>
<div class="point"> <div class="point">
<div class="pointItem" @click="drawQuadrant('现金流客户', 'rgba(0, 184, 105, 0.8)')">现金流客户</div> <div class="pointItem" @click="drawQuadrant('现金流客户', 'rgba(0, 184, 105, 0.8)')">现金流客户</div>
<div v-if="showAnswerFlag" style="margin-left: 3px; display: inline-block">
<span v-if="markArea4Error" style="color: red">X</span>
<span v-if="!markArea4Error" style="color: #00bb00">√</span>
</div>
</div> </div>
<div class="point"> <div class="point">
<div class="pointItem" @click="drawQuadrant('问题客户', 'rgba(177, 130, 192, 0.8)')">问题客户</div> <div class="pointItem" @click="drawQuadrant('问题客户', 'rgba(177, 130, 192, 0.8)')">问题客户</div>
<div v-if="showAnswerFlag" style="margin-left: 3px; display: inline-block">
<span v-if="markArea2Error" style="color: red">X</span>
<span v-if="!markArea2Error" style="color: #00bb00">√</span>
</div>
</div> </div>
<div class="point"> <div class="point">
<div class="pointItem" @click="drawQuadrant('瘦狗客户', 'rgba(254, 141, 42, 0.8)')">瘦狗客户</div> <div class="pointItem" @click="drawQuadrant('瘦狗客户', 'rgba(254, 141, 42, 0.8)')">瘦狗客户</div>
<div v-if="showAnswerFlag" style="margin-left: 3px; display: inline-block">
<span v-if="markArea3Error" style="color: red">X</span>
<span v-if="!markArea3Error" style="color: #00bb00">√</span>
</div>
</div> </div>
</div> </div>
</div> </div>
@ -288,6 +344,7 @@ import { downBlobFile } from "@/utils/index.js";
import { onMounted } from "vue"; import { onMounted } from "vue";
const { proxy } = getCurrentInstance(); const { proxy } = getCurrentInstance();
const baseUrl = import.meta.env.VITE_APP_BASE_API; const baseUrl = import.meta.env.VITE_APP_BASE_API;
const showAnswerFlag = ref(false);
const dialogVisible = ref(false); const dialogVisible = ref(false);
const knowledgeFlag = ref(false); const knowledgeFlag = ref(false);
const chart1OptionData = ref([]); const chart1OptionData = ref([]);
@ -301,6 +358,15 @@ const quadrant1Color = ref("");
const quadrant2Color = ref(""); const quadrant2Color = ref("");
const quadrant3Color = ref(""); const quadrant3Color = ref("");
const quadrant4Color = ref(""); const quadrant4Color = ref("");
const pointAError = ref(false);
const pointBError = ref(false);
const pointCError = ref(false);
const pointDError = ref(false);
const centerPointError = ref(false);
const markArea1Error = ref(false);
const markArea2Error = ref(false);
const markArea3Error = ref(false);
const markArea4Error = ref(false);
const step1Data = ref([ const step1Data = ref([
{ {
name: "A", name: "A",
@ -579,6 +645,7 @@ const option2 = ref({});
const drawPointNameStep4 = ref(""); const drawPointNameStep4 = ref("");
const drawPointColorStep4 = ref(""); const drawPointColorStep4 = ref("");
const pointInGridStep4 = ref([]); const pointInGridStep4 = ref([]);
const markCenterLineStep4 = ref([]);
//第五步定义数据 //第五步定义数据
const optionStep5 = ref({}); const optionStep5 = ref({});
const drawPointNameStep5 = ref(""); const drawPointNameStep5 = ref("");
@ -622,7 +689,7 @@ const drawPointStep4 = (point, color) => {
}; };
const step3EchartInit = () => { const step3EchartInit = () => {
var chartDom = document.getElementById("charts1"); var chartDom = document.getElementById("charts1");
var myChart = echarts.init(chartDom, "dark"); var myChart = echarts.init(chartDom);
// var option; // var option;
option.value = { option.value = {
@ -724,6 +791,9 @@ const step3EchartInit = () => {
color: drawPointColor.value, color: drawPointColor.value,
}); });
option.value && myChart.setOption(option.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(); // console.log();
// 所点击点的X轴坐标点所在X轴data的下标 // 所点击点的X轴坐标点所在X轴data的下标
// let xIndex = pointInGrid[0]; // let xIndex = pointInGrid[0];
@ -741,9 +811,26 @@ const step3EchartInit = () => {
}; };
const step4EchartInit = () => { const step4EchartInit = () => {
var chartDom = document.getElementById("charts2"); var chartDom = document.getElementById("charts2");
var myChart = echarts.init(chartDom, "dark"); var myChart = echarts.init(chartDom);
// var option; // var option;
// 中心线
const centerLine = [
{
name: "y",
xAxis: 5,
},
{
name: "x",
yAxis: 1000,
},
];
// 中心点
const centerMark = [
{
value: "中心点",
coord: [5, 1000],
},
];
option2.value = { option2.value = {
xAxis: { xAxis: {
name: "X", name: "X",
@ -801,14 +888,47 @@ const step4EchartInit = () => {
// // [6, 600], // // [6, 600],
// // [7, 1400], // // [7, 1400],
// ], // ],
data: chart2OptionData.value, data: chart1OptionData.value,
type: "scatter", 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); option2.value && myChart.setOption(option2.value);
myChart.getZr().on("click", function (param) { myChart.getZr().on("click", function (param) {
// markCenterLineStep4.value = [];
if (drawPointNameStep4.value == "") { if (drawPointNameStep4.value == "") {
proxy.$modal.msgError("请选择要绘制的点"); proxy.$modal.msgError("请选择要绘制的点");
return; return;
@ -819,6 +939,7 @@ const step4EchartInit = () => {
chart2OptionData.value.splice(i, 1); chart2OptionData.value.splice(i, 1);
} }
} }
markCenterLineStep4.value.splice(0, 2);
const pointInPixel = [param.offsetX, param.offsetY]; const pointInPixel = [param.offsetX, param.offsetY];
console.log("pointInPixel4", pointInPixel); console.log("pointInPixel4", pointInPixel);
//将偏移值转化为坐标值 //将偏移值转化为坐标值
@ -834,6 +955,18 @@ const step4EchartInit = () => {
name: drawPointNameStep4.value, name: drawPointNameStep4.value,
color: drawPointColorStep4.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); option2.value && myChart.setOption(option2.value);
}); });
}; };
@ -1107,7 +1240,7 @@ const step5EchartInit = () => {
optionStep5.value.series[0].markArea.data[2][0].itemStyle.color = quadrant3Color.value; optionStep5.value.series[0].markArea.data[2][0].itemStyle.color = quadrant3Color.value;
optionStep5.value.series[0].markArea.data[3][0].itemStyle.color = quadrant4Color.value; optionStep5.value.series[0].markArea.data[3][0].itemStyle.color = quadrant4Color.value;
var chartDom = document.getElementById("charts3"); var chartDom = document.getElementById("charts3");
var myChart = echarts.init(chartDom, "dark"); var myChart = echarts.init(chartDom);
optionStep5.value && myChart.setOption(optionStep5.value); optionStep5.value && myChart.setOption(optionStep5.value);
myChart.getZr().on("click", function (param) { myChart.getZr().on("click", function (param) {
if (drawPointColorStep5.value == "") { if (drawPointColorStep5.value == "") {
@ -1157,27 +1290,51 @@ const step1Submit = () => {
} }
if (step1Data.value[0].params1 && step1Data.value[0].params1 !== "3") { if (step1Data.value[0].params1 && step1Data.value[0].params1 !== "3") {
step1Error.value++; step1Error.value++;
step1Data.value[0].isError1 = true;
} else {
step1Data.value[0].isError1 = false;
} }
if (step1Data.value[0].params2 && step1Data.value[0].params2 !== "800") { if (step1Data.value[0].params2 && step1Data.value[0].params2 !== "800") {
step1Error.value++; step1Error.value++;
step1Data.value[0].isError2 = true;
} else {
step1Data.value[0].isError2 = false;
} }
if (step1Data.value[1].params1 && step1Data.value[1].params1 !== "4") { if (step1Data.value[1].params1 && step1Data.value[1].params1 !== "4") {
step1Error.value++; step1Error.value++;
step1Data.value[1].isError1 = true;
} else {
step1Data.value[1].isError1 = false;
} }
if (step1Data.value[1].params2 && step1Data.value[1].params2 !== "1200") { if (step1Data.value[1].params2 && step1Data.value[1].params2 !== "1200") {
step1Error.value++; step1Error.value++;
step1Data.value[1].isError2 = true;
} else {
step1Data.value[1].isError2 = false;
} }
if (step1Data.value[2].params1 && step1Data.value[2].params1 !== "6") { if (step1Data.value[2].params1 && step1Data.value[2].params1 !== "6") {
step1Error.value++; step1Error.value++;
step1Data.value[2].isError1 = true;
} else {
step1Data.value[2].isError1 = false;
} }
if (step1Data.value[2].params2 && step1Data.value[2].params2 !== "600") { if (step1Data.value[2].params2 && step1Data.value[2].params2 !== "600") {
step1Error.value++; step1Error.value++;
step1Data.value[2].isError2 = true;
} else {
step1Data.value[2].isError2 = false;
} }
if (step1Data.value[3].params1 && step1Data.value[3].params1 !== "7") { if (step1Data.value[3].params1 && step1Data.value[3].params1 !== "7") {
step1Error.value++; step1Error.value++;
step1Data.value[3].isError1 = true;
} else {
step1Data.value[3].isError1 = false;
} }
if (step1Data.value[3].params2 && step1Data.value[3].params2 !== "1400") { if (step1Data.value[3].params2 && step1Data.value[3].params2 !== "1400") {
step1Error.value++; step1Error.value++;
step1Data.value[3].isError2 = true;
} else {
step1Data.value[3].isError2 = false;
} }
console.log(step1Error.value, "错误数"); console.log(step1Error.value, "错误数");
proxy.$modal.msgSuccess("提交成功"); proxy.$modal.msgSuccess("提交成功");
@ -1195,9 +1352,15 @@ const step2Submit = () => {
} }
if (step2Data.value[4].params1 && step2Data.value[4].params1 !== "5") { if (step2Data.value[4].params1 && step2Data.value[4].params1 !== "5") {
step2Error.value++; step2Error.value++;
step2Data.value[4].isError1 = true;
} else {
step2Data.value[4].isError1 = false;
} }
if (step2Data.value[4].params2 && step2Data.value[4].params2 !== "1000") { if (step2Data.value[4].params2 && step2Data.value[4].params2 !== "1000") {
step2Error.value++; step2Error.value++;
step2Data.value[4].isError2 = true;
} else {
step2Data.value[4].isError2 = false;
} }
console.log(step2Error.value, "错误数"); console.log(step2Error.value, "错误数");
proxy.$modal.msgSuccess("提交成功"); proxy.$modal.msgSuccess("提交成功");
@ -1210,21 +1373,33 @@ const step3Submit = () => {
if (chart1OptionData.value[i].name == "A") { if (chart1OptionData.value[i].name == "A") {
if (Math.round(chart1OptionData.value[i].value[0]) != 3 || Math.round(chart1OptionData.value[i].value[1]) != 800) { if (Math.round(chart1OptionData.value[i].value[0]) != 3 || Math.round(chart1OptionData.value[i].value[1]) != 800) {
step3Error.value++; step3Error.value++;
pointAError.value = true;
} else {
pointAError.value = false;
} }
} }
if (chart1OptionData.value[i].name == "B") { if (chart1OptionData.value[i].name == "B") {
if (Math.round(chart1OptionData.value[i].value[0]) != 4 || Math.round(chart1OptionData.value[i].value[1]) != 1200) { if (Math.round(chart1OptionData.value[i].value[0]) != 4 || Math.round(chart1OptionData.value[i].value[1]) != 1200) {
step3Error.value++; step3Error.value++;
pointBError.value = true;
} else {
pointBError.value = false;
} }
} }
if (chart1OptionData.value[i].name == "C") { if (chart1OptionData.value[i].name == "C") {
if (Math.round(chart1OptionData.value[i].value[0]) != 6 || Math.round(chart1OptionData.value[i].value[1]) != 600) { if (Math.round(chart1OptionData.value[i].value[0]) != 6 || Math.round(chart1OptionData.value[i].value[1]) != 600) {
step3Error.value++; step3Error.value++;
pointCError.value = true;
} else {
pointCError.value = false;
} }
} }
if (chart1OptionData.value[i].name == "D") { if (chart1OptionData.value[i].name == "D") {
if (Math.round(chart1OptionData.value[i].value[0]) != 7 || Math.round(chart1OptionData.value[i].value[1]) != 1400) { if (Math.round(chart1OptionData.value[i].value[0]) != 7 || Math.round(chart1OptionData.value[i].value[1]) != 1400) {
step3Error.value++; step3Error.value++;
pointDError.value = true;
} else {
pointDError.value = false;
} }
} }
} }
@ -1243,6 +1418,9 @@ const step4Submit = () => {
if (Math.round(chart2OptionData.value[i].value[0]) != 5 || Math.round(chart2OptionData.value[i].value[1]) != 1000) { if (Math.round(chart2OptionData.value[i].value[0]) != 5 || Math.round(chart2OptionData.value[i].value[1]) != 1000) {
console.log(chart2OptionData.value[i]); console.log(chart2OptionData.value[i]);
step4Error.value++; step4Error.value++;
centerPointError.value = true;
} else {
centerPointError.value = false;
} }
} }
} }
@ -1254,15 +1432,27 @@ const step5Submit = () => {
step5Error.value = 0; step5Error.value = 0;
if (optionStep5.value.series[0].markArea.data[0][0].name != "明星客户") { if (optionStep5.value.series[0].markArea.data[0][0].name != "明星客户") {
step5Error.value++; step5Error.value++;
markArea1Error.value = true;
} else {
markArea1Error.value = false;
} }
if (optionStep5.value.series[0].markArea.data[1][0].name != "问题客户") { if (optionStep5.value.series[0].markArea.data[1][0].name != "问题客户") {
step5Error.value++; step5Error.value++;
markArea2Error.value = true;
} else {
markArea2Error.value = false;
} }
if (optionStep5.value.series[0].markArea.data[2][0].name != "瘦狗客户") { if (optionStep5.value.series[0].markArea.data[2][0].name != "瘦狗客户") {
step5Error.value++; step5Error.value++;
markArea3Error.value = true;
} else {
markArea3Error.value = false;
} }
if (optionStep5.value.series[0].markArea.data[3][0].name != "现金流客户") { if (optionStep5.value.series[0].markArea.data[3][0].name != "现金流客户") {
step5Error.value++; step5Error.value++;
markArea4Error.value = true;
} else {
markArea4Error.value = false;
} }
console.log(step5Error.value, "错误数"); console.log(step5Error.value, "错误数");
proxy.$modal.msgSuccess("提交成功"); proxy.$modal.msgSuccess("提交成功");
@ -1292,9 +1482,11 @@ const submitData = () => {
userId: JSON.parse(getUserInfo()).userId, userId: JSON.parse(getUserInfo()).userId,
taskName: "波士顿矩阵分析", taskName: "波士顿矩阵分析",
numberOfErrors: errorNum.value, numberOfErrors: errorNum.value,
subState: 1,
}) })
.then((res) => { .then((res) => {
proxy.$modal.msgSuccess("提交成功"); proxy.$modal.msgSuccess("提交成功");
showAnswerFlag.value = true;
}) })
.catch((error) => {}); .catch((error) => {});
}; };
@ -1448,7 +1640,8 @@ defineExpose({
<style scoped lang="scss"> <style scoped lang="scss">
.content { .content {
width: 100%; width: 100%;
background: rgba(0, 29, 64, 0.5); // background: rgba(0, 29, 64, 0.5);
background: #fff;
border: 1px solid #0452c6; border: 1px solid #0452c6;
padding: 10px; padding: 10px;
// opacity: 0.5; // opacity: 0.5;
@ -1471,6 +1664,7 @@ defineExpose({
} }
} }
.caseBack { .caseBack {
color: #000;
.title { .title {
font-weight: bold; font-weight: bold;
margin-top: 10px; margin-top: 10px;
@ -1510,9 +1704,10 @@ defineExpose({
align-items: center; align-items: center;
width: 945px; width: 945px;
height: 26px; height: 26px;
background: #003b75; // background: #003b75;
background: #fff8ee;
border-radius: 10px; border-radius: 10px;
border: 1px solid #0052a3; // border: 1px solid #0052a3;
font-size: 12px; font-size: 12px;
margin-top: 10px; margin-top: 10px;
img { img {
@ -1530,7 +1725,8 @@ defineExpose({
height: 19px; height: 19px;
padding-left: 10px; padding-left: 10px;
padding-right: 10px; padding-right: 10px;
background: #002651; // background: #002651;
background: #fff;
border: 1px solid #67b3d6; border: 1px solid #67b3d6;
text-align: center; text-align: center;
line-height: 19px; line-height: 19px;
@ -1554,9 +1750,17 @@ defineExpose({
margin-bottom: 20px; margin-bottom: 20px;
} }
} }
// ::v-deep .el-table tr {
// background-color: #002652 !important;
// color: #fff;
// }
::v-deep .el-table tr { ::v-deep .el-table tr {
background-color: #002652 !important; background-color: #fff !important;
color: #fff; color: #000;
}
/* 将悬停背景色改为红色 */
::v-deep .el-table--enable-row-hover .el-table__body tr:hover > td {
background-color: #f5f7fa !important;
} }
::v-deep .el-table td { ::v-deep .el-table td {
padding-top: 4px; padding-top: 4px;

@ -17,7 +17,8 @@
<span>案例背景:</span> <span>案例背景:</span>
</div> </div>
<span style="line-height: 25px; font-size: 14px"> <span style="line-height: 25px; font-size: 14px">
漏斗分析模型已经广泛应用于流量监控、产品目标转化等日常数据运营与数据分析的工作中。比如一个电商APP,用户登录APP后,会看到广告页。点击广告页后会看到产品详情,如果用户想购买,就点击进去购物车页面,再进入支付页面,完成支付。每一步,用户都有流失的可能,因此两个步骤之间有一定的转化率。<br /> 漏斗分析模型已经广泛应用于流量监控、产品目标转化等日常数据运营与数据分析的工作中。比如一个电商APP,用户登录APP后,会看到广告页。点击广告页后会看到产品详情,如果用户想购买,就点击进去购物车页面,再进入支付页面,完成支付。每一步,用户都有流失的可能,因此两个步骤之间有一定的转化率。
<br />
现有以下某购物APP各个流程节点的用户数据,需要用漏斗模型进行分析: 现有以下某购物APP各个流程节点的用户数据,需要用漏斗模型进行分析:
</span> </span>
<div style="margin-top: 10px; display: flex"> <div style="margin-top: 10px; display: flex">
@ -31,18 +32,12 @@
backgroundColor: '#6A7DE9!important', backgroundColor: '#6A7DE9!important',
}" }"
> >
<el-table-column label="" align="center" prop="data1"> <el-table-column label="" align="center" prop="data1"></el-table-column>
</el-table-column> <el-table-column label="浏览" align="center" prop="data2"></el-table-column>
<el-table-column label="浏览" align="center" prop="data2"> <el-table-column label="购物车" align="center" prop="data3"></el-table-column>
</el-table-column> <el-table-column label="订单" align="center" prop="data4"></el-table-column>
<el-table-column label="购物车" align="center" prop="data3"> <el-table-column label="支付" align="center" prop="data5"></el-table-column>
</el-table-column> <el-table-column label="完成交易" align="center" prop="data6"></el-table-column>
<el-table-column label="订单" align="center" prop="data4">
</el-table-column>
<el-table-column label="支付" align="center" prop="data5">
</el-table-column>
<el-table-column label="完成交易" align="center" prop="data6">
</el-table-column>
</el-table> </el-table>
<div class="download" @click="downloadData">下载数据</div> <div class="download" @click="downloadData">下载数据</div>
</div> </div>
@ -54,10 +49,14 @@
<span>第一步,转化率计算</span> <span>第一步,转化率计算</span>
</div> </div>
<span style="line-height: 25px; font-size: 14px"> <span style="line-height: 25px; font-size: 14px">
转化率=下一步人数/上一步人数*100% <br /> 转化率=下一步人数/上一步人数*100%
流失率=1—转化率 <br /> <br />
总体转化率/最终转化率=该步人数/总访问量(浏览量)*100% <br /> 流失率=1—转化率
计算结果保留小数点后一位 <br /> <br />
总体转化率/最终转化率=该步人数/总访问量(浏览量)*100%
<br />
计算结果保留小数点后一位
<br />
</span> </span>
<div style="margin-top: 10px; display: flex"> <div style="margin-top: 10px; display: flex">
<el-table <el-table
@ -70,66 +69,55 @@
backgroundColor: '#6A7DE9!important', backgroundColor: '#6A7DE9!important',
}" }"
> >
<el-table-column label="" align="center" prop="data1"> <el-table-column label="" align="center" prop="data1"></el-table-column>
</el-table-column>
<el-table-column label="浏览" align="center" prop="data2"> <el-table-column label="浏览" align="center" prop="data2">
<template #default="scope"> <template #default="scope">
<el-input <el-input v-if="scope.$index != 0" v-model="scope.row.params1" placeholder="请输入" style="width: 100px"></el-input>
v-if="scope.$index != 0" <span v-if="scope.$index != 0">%</span>
v-model="scope.row.params1" <div v-if="showAnswerFlag & (scope.$index != 0)" style="margin-left: 3px; display: inline-block">
placeholder="请输入" <span v-if="scope.row.isError1" style="color: red">X</span>
style="width: 100px" <span v-if="!scope.row.isError1" style="color: #00bb00">√</span>
> </div>
</el-input
><span v-if="scope.$index != 0"> %</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="购物车" align="center" prop="data3"> <el-table-column label="购物车" align="center" prop="data3">
<template #default="scope"> <template #default="scope">
<el-input <el-input v-if="scope.$index != 0" v-model="scope.row.params2" placeholder="请输入" style="width: 100px"></el-input>
v-if="scope.$index != 0" <span v-if="scope.$index != 0">%</span>
v-model="scope.row.params2" <div v-if="showAnswerFlag & (scope.$index != 0)" style="margin-left: 3px; display: inline-block">
placeholder="请输入" <span v-if="scope.row.isError2" style="color: red">X</span>
style="width: 100px" <span v-if="!scope.row.isError2" style="color: #00bb00">√</span>
> </div>
</el-input
><span v-if="scope.$index != 0"> %</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="订单" align="center" prop="data4"> <el-table-column label="订单" align="center" prop="data4">
<template #default="scope"> <template #default="scope">
<el-input <el-input v-if="scope.$index != 0" v-model="scope.row.params3" placeholder="请输入" style="width: 100px"></el-input>
v-if="scope.$index != 0" <span v-if="scope.$index != 0">%</span>
v-model="scope.row.params3" <div v-if="showAnswerFlag & (scope.$index != 0)" style="margin-left: 3px; display: inline-block">
placeholder="请输入" <span v-if="scope.row.isError3" style="color: red">X</span>
style="width: 100px" <span v-if="!scope.row.isError3" style="color: #00bb00">√</span>
> </div>
</el-input
><span v-if="scope.$index != 0"> %</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="支付" align="center" prop="data5"> <el-table-column label="支付" align="center" prop="data5">
<template #default="scope"> <template #default="scope">
<el-input <el-input v-if="scope.$index != 0" v-model="scope.row.params4" placeholder="请输入" style="width: 100px"></el-input>
v-if="scope.$index != 0" <span v-if="scope.$index != 0">%</span>
v-model="scope.row.params4" <div v-if="showAnswerFlag & (scope.$index != 0)" style="margin-left: 3px; display: inline-block">
placeholder="请输入" <span v-if="scope.row.isError4" style="color: red">X</span>
style="width: 100px" <span v-if="!scope.row.isError4" style="color: #00bb00">√</span>
> </div>
</el-input
><span v-if="scope.$index != 0"> %</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="完成交易" align="center" prop="data6"> <el-table-column label="完成交易" align="center" prop="data6">
<template #default="scope"> <template #default="scope">
<el-input <el-input v-if="scope.$index != 0" v-model="scope.row.params5" placeholder="请输入" style="width: 100px"></el-input>
v-if="scope.$index != 0" <span v-if="scope.$index != 0">%</span>
v-model="scope.row.params5" <div v-if="showAnswerFlag & (scope.$index != 0)" style="margin-left: 3px; display: inline-block">
placeholder="请输入" <span v-if="scope.row.isError5" style="color: red">X</span>
style="width: 100px" <span v-if="!scope.row.isError5" style="color: #00bb00">√</span>
> </div>
</el-input
><span v-if="scope.$index != 0"> %</span>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
@ -142,85 +130,87 @@
<img src="@/assets/images/步骤.png" alt="" /> <img src="@/assets/images/步骤.png" alt="" />
<span>第二步,绘制漏斗图</span> <span>第二步,绘制漏斗图</span>
</div> </div>
<span style="line-height: 25px; font-size: 14px"> <span style="line-height: 25px; font-size: 14px">以各个页面节点的人数为统计指标,绘制漏斗图:</span>
以各个页面节点的人数为统计指标,绘制漏斗图:
</span>
<div style="margin-top: 10px; display: flex"> <div style="margin-top: 10px; display: flex">
<div id="funnel" style="width: 520px; height: 400px"></div> <div id="funnel" style="width: 520px; height: 400px"></div>
<div style="margin-top: 75px"> <div style="margin-top: 75px">
<div> <div>
<el-select <div style="display: flex; align-items: center; justify-content: center; margin-bottom: 28px">
v-model="step2Select1" <el-select v-model="step2Select1" placeholder="请选择" style="width: 130px" @change="selectData($event, 4)">
placeholder="请选择"
style="width: 130px; margin-bottom: 28px"
>
<el-option :label="'浏览2071'" :value="'浏览2071'" /> <el-option :label="'浏览2071'" :value="'浏览2071'" />
<el-option :label="'购物车622'" :value="'购物车622'" /> <el-option :label="'购物车622'" :value="'购物车622'" />
<el-option :label="'订单284'" :value="'订单284'" /> <el-option :label="'订单284'" :value="'订单284'" />
<el-option :label="'支付235'" :value="'支付235'" /> <el-option :label="'支付235'" :value="'支付235'" />
<el-option :label="'完成交易223'" :value="'完成交易223'" /> <el-option :label="'完成交易223'" :value="'完成交易223'" />
</el-select> </el-select>
<div v-if="showAnswerFlag" style="margin-left: 3px">
<span v-if="step2Select1 != '浏览2071'" style="color: red">X</span>
<span v-if="step2Select1 == '浏览2071'" style="color: #00bb00">√</span>
</div>
</div>
</div> </div>
<div> <div>
<el-select <div style="display: flex; align-items: center; justify-content: center; margin-bottom: 32px">
v-model="step2Select2" <el-select v-model="step2Select2" placeholder="请选择" style="width: 130px" @change="selectData($event, 3)">
placeholder="请选择"
style="width: 130px; margin-bottom: 32px"
>
<el-option :label="'浏览2071'" :value="'浏览2071'" /> <el-option :label="'浏览2071'" :value="'浏览2071'" />
<el-option :label="'购物车622'" :value="'购物车622'" /> <el-option :label="'购物车622'" :value="'购物车622'" />
<el-option :label="'订单284'" :value="'订单284'" /> <el-option :label="'订单284'" :value="'订单284'" />
<el-option :label="'支付235'" :value="'支付235'" /> <el-option :label="'支付235'" :value="'支付235'" />
<el-option :label="'完成交易223'" :value="'完成交易223'" /> <el-option :label="'完成交易223'" :value="'完成交易223'" />
</el-select> </el-select>
<div v-if="showAnswerFlag" style="margin-left: 3px">
<span v-if="step2Select2 != '购物车622'" style="color: red">X</span>
<span v-if="step2Select2 == '购物车622'" style="color: #00bb00">√</span>
</div>
</div>
</div> </div>
<div> <div>
<el-select <div style="display: flex; align-items: center; justify-content: center; margin-bottom: 30px">
v-model="step2Select3" <el-select v-model="step2Select3" placeholder="请选择" style="width: 130px" @change="selectData($event, 2)">
placeholder="请选择"
style="width: 130px; margin-bottom: 30px"
>
<el-option :label="'浏览2071'" :value="'浏览2071'" /> <el-option :label="'浏览2071'" :value="'浏览2071'" />
<el-option :label="'购物车622'" :value="'购物车622'" /> <el-option :label="'购物车622'" :value="'购物车622'" />
<el-option :label="'订单284'" :value="'订单284'" /> <el-option :label="'订单284'" :value="'订单284'" />
<el-option :label="'支付235'" :value="'支付235'" /> <el-option :label="'支付235'" :value="'支付235'" />
<el-option :label="'完成交易223'" :value="'完成交易223'" /> <el-option :label="'完成交易223'" :value="'完成交易223'" />
</el-select> </el-select>
<div v-if="showAnswerFlag" style="margin-left: 3px">
<span v-if="step2Select3 != '订单284'" style="color: red">X</span>
<span v-if="step2Select3 == '订单284'" style="color: #00bb00">√</span>
</div>
</div>
</div> </div>
<div> <div>
<el-select <div style="display: flex; align-items: center; justify-content: center; margin-bottom: 30px">
v-model="step2Select4" <el-select v-model="step2Select4" placeholder="请选择" style="width: 130px" @change="selectData($event, 1)">
placeholder="请选择"
style="width: 130px; margin-bottom: 30px"
>
<el-option :label="'浏览2071'" :value="'浏览2071'" /> <el-option :label="'浏览2071'" :value="'浏览2071'" />
<el-option :label="'购物车622'" :value="'购物车622'" /> <el-option :label="'购物车622'" :value="'购物车622'" />
<el-option :label="'订单284'" :value="'订单284'" /> <el-option :label="'订单284'" :value="'订单284'" />
<el-option :label="'支付235'" :value="'支付235'" /> <el-option :label="'支付235'" :value="'支付235'" />
<el-option :label="'完成交易223'" :value="'完成交易223'" /> <el-option :label="'完成交易223'" :value="'完成交易223'" />
</el-select> </el-select>
<div v-if="showAnswerFlag" style="margin-left: 3px">
<span v-if="step2Select4 != '支付235'" style="color: red">X</span>
<span v-if="step2Select4 == '支付235'" style="color: #00bb00">√</span>
</div>
</div>
</div> </div>
<div> <div>
<el-select <div style="display: flex; align-items: center; justify-content: center; margin-bottom: 30px">
v-model="step2Select5" <el-select v-model="step2Select5" placeholder="请选择" style="width: 130px" @change="selectData($event, 0)">
placeholder="请选择"
style="width: 130px; margin-bottom: 30px"
>
<el-option :label="'浏览2071'" :value="'浏览2071'" /> <el-option :label="'浏览2071'" :value="'浏览2071'" />
<el-option :label="'购物车622'" :value="'购物车622'" /> <el-option :label="'购物车622'" :value="'购物车622'" />
<el-option :label="'订单284'" :value="'订单284'" /> <el-option :label="'订单284'" :value="'订单284'" />
<el-option :label="'支付235'" :value="'支付235'" /> <el-option :label="'支付235'" :value="'支付235'" />
<el-option :label="'完成交易223'" :value="'完成交易223'" /> <el-option :label="'完成交易223'" :value="'完成交易223'" />
</el-select> </el-select>
<div v-if="showAnswerFlag" style="margin-left: 3px">
<span v-if="step2Select5 != '完成交易223'" style="color: red">X</span>
<span v-if="step2Select5 == '完成交易223'" style="color: #00bb00">√</span>
</div>
</div> </div>
</div> </div>
<div
class="submit"
style="margin-top: 70px; margin-left: 100px"
@click="step2Submit"
>
提交
</div> </div>
<div class="submit" style="margin-top: 70px; margin-left: 100px" @click="step2Submit">提交</div>
</div> </div>
</div> </div>
<div class="line"></div> <div class="line"></div>
@ -229,42 +219,37 @@
<img src="@/assets/images/步骤.png" alt="" /> <img src="@/assets/images/步骤.png" alt="" />
<span>第三步,结果分析</span> <span>第三步,结果分析</span>
</div> </div>
<span style="line-height: 25px; font-size: 14px"> <span style="line-height: 25px; font-size: 14px">基于转化率结果计算和图标分析,得出结论:</span>
基于转化率结果计算和图标分析,得出结论:
</span>
<div style="margin-top: 10px; display: flex"> <div style="margin-top: 10px; display: flex">
<div> <div>
<div> <div>
<span>流失率排第一位的:</span> <span>流失率排第一位的:</span>
<el-select <el-select v-model="step3Select1" placeholder="请选择" style="width: 160px">
v-model="step3Select1"
placeholder="请选择"
style="width: 160px"
>
<el-option :label="'浏览--购物车'" :value="'浏览--购物车'" /> <el-option :label="'浏览--购物车'" :value="'浏览--购物车'" />
<el-option :label="'购物车--订单'" :value="'购物车--订单'" /> <el-option :label="'购物车--订单'" :value="'购物车--订单'" />
<el-option :label="'订单--支付'" :value="'订单--支付'" /> <el-option :label="'订单--支付'" :value="'订单--支付'" />
<el-option :label="'支付--完成交易'" :value="'付--完成交易'" /> <el-option :label="'支付--完成交易'" :value="'付--完成交易'" />
</el-select> </el-select>
<div v-if="showAnswerFlag" style="margin-left: 3px;display:inline-block">
<span v-if="step3Select1 != '浏览--购物车'" style="color: red">X</span>
<span v-if="step3Select1 == '浏览--购物车'" style="color: #00bb00">√</span>
</div>
</div> </div>
<br /> <br />
<div> <div>
<span>流失率排第二位的:</span> <span>流失率排第二位的:</span>
<el-select <el-select v-model="step3Select2" placeholder="请选择" style="width: 160px">
v-model="step3Select2"
placeholder="请选择"
style="width: 160px"
>
<el-option :label="'浏览--购物车'" :value="'浏览--购物车'" /> <el-option :label="'浏览--购物车'" :value="'浏览--购物车'" />
<el-option :label="'购物车--订单'" :value="'购物车--订单'" /> <el-option :label="'购物车--订单'" :value="'购物车--订单'" />
<el-option :label="'订单--支付'" :value="'订单--支付'" /> <el-option :label="'订单--支付'" :value="'订单--支付'" />
<el-option :label="'支付--完成交易'" :value="'付--完成交易'" /> <el-option :label="'支付--完成交易'" :value="'付--完成交易'" />
</el-select> </el-select>
<div v-if="showAnswerFlag" style="margin-left: 3px;display:inline-block">
<span v-if="step3Select2 != '购物车--订单'" style="color: red">X</span>
<span v-if="step3Select2 == '购物车--订单'" style="color: #00bb00">√</span>
</div>
</div> </div>
<p> <p>注:实际运用时 ,转化率需要与不同时期比较、与竞争对手、行业平均水平比较,分析的结果相对准确些。</p>
注:实际运用时
,转化率需要与不同时期比较、与竞争对手、行业平均水平比较,分析的结果相对准确些。
</p>
</div> </div>
<div class="submit" @click="step3Submit">提交</div> <div class="submit" @click="step3Submit">提交</div>
@ -276,30 +261,34 @@
<img src="@/assets/images/步骤.png" alt="" /> <img src="@/assets/images/步骤.png" alt="" />
<span>第四步,营销运营改进</span> <span>第四步,营销运营改进</span>
</div> </div>
<span style="line-height: 25px; font-size: 14px">针对转换率较低的环节步骤,制定改善措施:</span>
<br />
<span style="line-height: 25px; font-size: 14px"> <span style="line-height: 25px; font-size: 14px">
针对转换率较低的环节步骤,制定改善措施: </span 一、简化购物流程
><br /> <br />
<span style="line-height: 25px; font-size: 14px"> 购物车转化率受到购物流程的影响。如果购物流程复杂或繁琐,消费者可能会因为不方便而放弃购买。因此,简化购物流程是提高购物车转化率的关键。
一、简化购物流程<br /> <br />
购物车转化率受到购物流程的影响。如果购物流程复杂或繁琐,消费者可能会因为不方便而放弃购买。因此,简化购物流程是提高购物车转化率的关键。<br /> 1. 减少步骤:尽量减少购买过程中的步骤和页面数量。消费者希望能够快速完成购买,如果购买过程过于复杂,他们可能会选择放弃。
1. <br />
减少步骤:尽量减少购买过程中的步骤和页面数量。消费者希望能够快速完成购买,如果购买过程过于复杂,他们可能会选择放弃。<br /> 2. 简化表单:简化购买表单,只收集必要的信息。过多的信息收集可能会让消费者感到烦扰,从而影响购买意愿。
2. </span>
简化表单:简化购买表单,只收集必要的信息。过多的信息收集可能会让消费者感到烦扰,从而影响购买意愿。 </span <br />
><br />
<span style="line-height: 25px; font-size: 14px"> <span style="line-height: 25px; font-size: 14px">
二、优化产品页面<br /> 二、优化产品页面
产品页面是消费者了解和选择产品的关键环节。优化产品页面可以提高购物车转化率。<br /> <br />
1. 产品页面是消费者了解和选择产品的关键环节。优化产品页面可以提高购物车转化率。
清晰的产品信息:确保产品页面上提供清晰、详细的产品信息,包括产品描述、规格、图片等。消费者需要充分了解产品才能做出购买决策。<br /> <br />
2. 1. 清晰的产品信息:确保产品页面上提供清晰、详细的产品信息,包括产品描述、规格、图片等。消费者需要充分了解产品才能做出购买决策。
强调产品优势和价值:突出产品的独特卖点和优势,让消费者明白购买该产品的价值和好处。<br /> <br />
3. 2. 强调产品优势和价值:突出产品的独特卖点和优势,让消费者明白购买该产品的价值和好处。
用户评价和评级:展示其他消费者的评价和评级可以增加消费者对产品的信任度和购买意愿。<br /> <br />
4. 3. 用户评价和评级:展示其他消费者的评价和评级可以增加消费者对产品的信任度和购买意愿。
清晰的购买按钮:在产品页面上放置清晰、醒目的购买按钮,方便消费者快速添加产品到购物车。<br /> <br />
比如下决心改进广告页,更换了素材,更换了页面布局,最后有了ABC版本,这时候可以观察每个版本效果。如下图,持续改进广告页以后,能看到广告页点击有了提升,最终转化率也提升了。 </span 4. 清晰的购买按钮:在产品页面上放置清晰、醒目的购买按钮,方便消费者快速添加产品到购物车。
><br /> <br />
比如下决心改进广告页,更换了素材,更换了页面布局,最后有了ABC版本,这时候可以观察每个版本效果。如下图,持续改进广告页以后,能看到广告页点击有了提升,最终转化率也提升了。
</span>
<br />
<img src="@/assets/images/u3812.png" alt="" /> <img src="@/assets/images/u3812.png" alt="" />
</div> </div>
@ -325,6 +314,7 @@ import * as echarts from "echarts";
import { downBlobFile } from "@/utils/index.js"; import { downBlobFile } from "@/utils/index.js";
import { onMounted } from "vue"; import { onMounted } from "vue";
const { proxy } = getCurrentInstance(); const { proxy } = getCurrentInstance();
const funnelData = ref([223, 235, 284, 622, 2071]);
const dialogVisible = ref(false); const dialogVisible = ref(false);
const step2Select1 = ref(""); const step2Select1 = ref("");
const step2Select2 = ref(""); const step2Select2 = ref("");
@ -596,9 +586,9 @@ const typeData = ref([
// }, // },
// ], // ],
// }; // };
const option = { const option = ref({
title: { title: {
text: '漏斗图', text: "漏斗图",
textStyle: { textStyle: {
color: "#fff", color: "#fff",
}, },
@ -616,80 +606,68 @@ const option = {
}, },
}, },
grid: { grid: {
left: '3%', left: "3%",
right: '4%', right: "4%",
bottom: '3%', bottom: "3%",
containLabel: true containLabel: true,
}, },
xAxis: { xAxis: {
show:false show: false,
// type: 'value', // type: 'value',
// boundaryGap: [0, 0.01] // boundaryGap: [0, 0.01]
}, },
yAxis: { yAxis: {
type: 'category', type: "category",
data: ['', '', '', '', ''], data: ["", "", "", "", ""],
position: 'center' position: "center",
}, },
series: [ series: [
{ {
name: '', name: "",
stack: 'one', stack: "one",
type: 'bar', type: "bar",
barWidth: '60%', barWidth: "60%",
data: [1120, 1113, 1090, 920, 220], data: [1120, 1113, 1090, 920, 220],
itemStyle: { itemStyle: {
normal: { normal: {
//这里是重点 //这里是重点
color: function (params) { color: function (params) {
// 颜色设置透明 // 颜色设置透明
var colorList = [ 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)"];
'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]; return colorList[params.dataIndex];
} },
} },
} },
}, },
{ {
stack: 'one', stack: "one",
name: '', name: "",
type: 'bar', type: "bar",
barWidth: '60%', barWidth: "60%",
data: funnelData.value,
data: [223, 235, 284, 622, 2071], // data: [223, 235, 284, 622, 2071],
itemStyle: { itemStyle: {
normal: { normal: {
//这里是重点 //这里是重点
color: function (params) { color: function (params) {
// 颜色设置透明 // 颜色设置透明
var colorList = [ var colorList = ["#009FF1", "#003DA3", "#00B869", "#FE8D2A", "#FB54A1"];
'#009FF1',
'#003DA3',
'#00B869',
'#FE8D2A',
'#FB54A1',
];
return colorList[params.dataIndex]; return colorList[params.dataIndex];
} },
}, },
borderColor: "#fff", borderColor: "#fff",
borderWidth: 1, borderWidth: 1,
} },
} },
] ],
} });
const step1Error = ref(0); const step1Error = ref(0);
const step2Error = ref(0); const step2Error = ref(0);
const step3Error = ref(0); const step3Error = ref(0);
const step1AnswerFlag = ref(false); const step1AnswerFlag = ref(false);
const step2AnswerFlag = ref(false); const step2AnswerFlag = ref(false);
const step3AnswerFlag = ref(false); const step3AnswerFlag = ref(false);
const showAnswerFlag = ref(false);
const errorNum = ref(0); const errorNum = ref(0);
const baseUrl = import.meta.env.VITE_APP_BASE_API; const baseUrl = import.meta.env.VITE_APP_BASE_API;
onBeforeUnmount(() => { onBeforeUnmount(() => {
@ -698,9 +676,30 @@ onBeforeUnmount(() => {
onMounted(() => { onMounted(() => {
getData(); getData();
var chartDom = document.getElementById("funnel"); var chartDom = document.getElementById("funnel");
var myChart = echarts.init(chartDom,); var myChart = echarts.init(chartDom);
option && myChart.setOption(option); 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) => { const moveUp = (index, row) => {
console.log("上移", index, row); console.log("上移", index, row);
if (index > 0) { if (index > 0) {
@ -726,13 +725,7 @@ const step1Submit = () => {
step1Error.value = 0; step1Error.value = 0;
const step1DataSlice = step1Data.value.slice(1); const step1DataSlice = step1Data.value.slice(1);
for (let i in step1DataSlice) { for (let i in step1DataSlice) {
if ( if (!step1DataSlice[i].params1 || !step1DataSlice[i].params2 || !step1DataSlice[i].params3 || !step1DataSlice[i].params4 || !step1DataSlice[i].params5) {
!step1DataSlice[i].params1 ||
!step1DataSlice[i].params2 ||
!step1DataSlice[i].params3 ||
!step1DataSlice[i].params4 ||
!step1DataSlice[i].params5
) {
proxy.$modal.msgError("请先完成所有填空"); proxy.$modal.msgError("请先完成所有填空");
return; return;
} }
@ -740,56 +733,93 @@ const step1Submit = () => {
//判断对错 //判断对错
if (step1DataSlice[0].params1 && step1DataSlice[0].params1 !== "100") { if (step1DataSlice[0].params1 && step1DataSlice[0].params1 !== "100") {
step1Error.value++; step1Error.value++;
step1DataSlice[0].isError1 = true;
} else {
step1DataSlice[0].isError1 = false;
} }
if ( if (step1DataSlice[0].params2 && step1DataSlice[0].params2 !== "30.0" && step1DataSlice[0].params2 !== "30") {
step1DataSlice[0].params2 &&
step1DataSlice[0].params2 !== "30.0" &&
step1DataSlice[0].params2 !== "30"
) {
step1Error.value++; step1Error.value++;
step1DataSlice[0].isError2 = true;
} else {
step1DataSlice[0].isError2 = false;
} }
if (step1DataSlice[0].params3 && step1DataSlice[0].params3 !== "45.7") { if (step1DataSlice[0].params3 && step1DataSlice[0].params3 !== "45.7") {
step1Error.value++; step1Error.value++;
step1DataSlice[0].isError3 = true;
} else {
step1DataSlice[0].isError3 = false;
} }
if (step1DataSlice[0].params4 && step1DataSlice[0].params4 !== "82.7") { if (step1DataSlice[0].params4 && step1DataSlice[0].params4 !== "82.7") {
step1Error.value++; step1Error.value++;
step1DataSlice[0].isError4 = true;
} else {
step1DataSlice[0].isError4 = false;
} }
if (step1DataSlice[0].params5 && step1DataSlice[0].params5 !== "94.9") { if (step1DataSlice[0].params5 && step1DataSlice[0].params5 !== "94.9") {
step1Error.value++; step1Error.value++;
step1DataSlice[0].isError5 = true;
} else {
step1DataSlice[0].isError5 = false;
} }
if (step1DataSlice[1].params1 && step1DataSlice[1].params1 !== "0") { if (step1DataSlice[1].params1 && step1DataSlice[1].params1 !== "0") {
step1Error.value++; step1Error.value++;
step1DataSlice[1].isError1 = true;
} else {
step1DataSlice[1].isError1 = false;
} }
if (step1DataSlice[1].params2 && step1DataSlice[1].params2 !== "70") { if (step1DataSlice[1].params2 && step1DataSlice[1].params2 !== "70") {
step1Error.value++; step1Error.value++;
step1DataSlice[1].isError2 = true;
} else {
step1DataSlice[1].isError2 = false;
} }
if (step1DataSlice[1].params3 && step1DataSlice[1].params3 !== "54.3") { if (step1DataSlice[1].params3 && step1DataSlice[1].params3 !== "54.3") {
step1Error.value++; step1Error.value++;
step1DataSlice[1].isError3 = true;
} else {
step1DataSlice[1].isError3 = false;
} }
if (step1DataSlice[1].params4 && step1DataSlice[1].params4 !== "17.3") { if (step1DataSlice[1].params4 && step1DataSlice[1].params4 !== "17.3") {
step1Error.value++; step1Error.value++;
step1DataSlice[1].isError4 = true;
} else {
step1DataSlice[1].isError4 = false;
} }
if (step1DataSlice[1].params5 && step1DataSlice[1].params5 !== "5.1") { if (step1DataSlice[1].params5 && step1DataSlice[1].params5 !== "5.1") {
step1Error.value++; step1Error.value++;
step1DataSlice[1].isError5 = true;
} else {
step1DataSlice[1].isError5 = false;
} }
if (step1DataSlice[2].params1 && step1DataSlice[2].params1 !== "100") { if (step1DataSlice[2].params1 && step1DataSlice[2].params1 !== "100") {
step1Error.value++; step1Error.value++;
step1DataSlice[2].isError1 = true;
} else {
step1DataSlice[2].isError1 = false;
} }
if ( if (step1DataSlice[2].params2 && step1DataSlice[2].params2 !== "30.0" && step1DataSlice[2].params2 !== "30") {
step1DataSlice[2].params2 &&
step1DataSlice[2].params2 !== "30.0" &&
step1DataSlice[2].params2 !== "30"
) {
step1Error.value++; step1Error.value++;
step1DataSlice[2].isError2 = true;
} else {
step1DataSlice[2].isError2 = false;
} }
if (step1DataSlice[2].params3 && step1DataSlice[2].params3 !== "13.7") { if (step1DataSlice[2].params3 && step1DataSlice[2].params3 !== "13.7") {
step1Error.value++; step1Error.value++;
step1DataSlice[2].isError3 = true;
} else {
step1DataSlice[2].isError3 = false;
} }
if (step1DataSlice[2].params4 && step1DataSlice[2].params4 !== "11.3") { if (step1DataSlice[2].params4 && step1DataSlice[2].params4 !== "11.3") {
step1Error.value++; step1Error.value++;
step1DataSlice[2].isError4 = true;
} else {
step1DataSlice[2].isError4 = false;
} }
if (step1DataSlice[2].params5 && step1DataSlice[2].params5 !== "10.8") { if (step1DataSlice[2].params5 && step1DataSlice[2].params5 !== "10.8") {
step1Error.value++; step1Error.value++;
step1DataSlice[2].isError5 = true;
} else {
step1DataSlice[2].isError5 = false;
} }
console.log(step1Error.value, "错误数"); console.log(step1Error.value, "错误数");
proxy.$modal.msgSuccess("提交成功"); proxy.$modal.msgSuccess("提交成功");
@ -798,13 +828,7 @@ const step1Submit = () => {
}; };
const step2Submit = () => { const step2Submit = () => {
step2Error.value = 0; step2Error.value = 0;
if ( if (step2Select1.value == "" || step2Select2.value == "" || step2Select3.value == "" || step2Select4.value == "" || step2Select5.value == "") {
step2Select1.value == "" ||
step2Select2.value == "" ||
step2Select3.value == "" ||
step2Select4.value == "" ||
step2Select5.value == ""
) {
proxy.$modal.msgError("请先完成选择"); proxy.$modal.msgError("请先完成选择");
return; return;
} }
@ -957,11 +981,7 @@ const getData = () => {
.catch((error) => {}); .catch((error) => {});
}; };
const submitData = () => { const submitData = () => {
if ( if (!step1AnswerFlag.value || !step2AnswerFlag.value || !step3AnswerFlag.value) {
!step1AnswerFlag.value ||
!step2AnswerFlag.value ||
!step3AnswerFlag.value
) {
proxy.$modal.msgError("请先完成所有步骤!"); proxy.$modal.msgError("请先完成所有步骤!");
return; return;
} }
@ -972,9 +992,11 @@ const submitData = () => {
userId: JSON.parse(getUserInfo()).userId, userId: JSON.parse(getUserInfo()).userId,
taskName: "转化分析-漏斗模型", taskName: "转化分析-漏斗模型",
numberOfErrors: errorNum.value, numberOfErrors: errorNum.value,
subState: 1,
}) })
.then((res) => { .then((res) => {
proxy.$modal.msgSuccess("提交成功"); proxy.$modal.msgSuccess("提交成功");
showAnswerFlag.value = true;
}) })
.catch((error) => {}); .catch((error) => {});
// console.log(666); // console.log(666);
@ -1014,7 +1036,8 @@ defineExpose({
<style scoped lang="scss"> <style scoped lang="scss">
.content { .content {
width: 100%; width: 100%;
background: rgba(0, 29, 64, 0.5); // background: rgba(0, 29, 64, 0.5);
background: #fff;
border: 1px solid #0452c6; border: 1px solid #0452c6;
padding: 10px; padding: 10px;
// opacity: 0.5; // opacity: 0.5;
@ -1037,6 +1060,7 @@ defineExpose({
} }
} }
.caseBack { .caseBack {
color: #000;
.title { .title {
font-weight: bold; font-weight: bold;
margin-top: 10px; margin-top: 10px;
@ -1095,9 +1119,17 @@ defineExpose({
margin-bottom: 20px; margin-bottom: 20px;
} }
} }
// ::v-deep .el-table tr {
// background-color: #002652 !important;
// color: #fff;
// }
::v-deep .el-table tr { ::v-deep .el-table tr {
background-color: #002652 !important; background-color: #fff !important;
color: #fff; color: #000;
}
/* 将悬停背景色改为红色 */
::v-deep .el-table--enable-row-hover .el-table__body tr:hover > td {
background-color: #f5f7fa !important;
} }
::v-deep .el-table td { ::v-deep .el-table td {
padding-top: 4px; padding-top: 4px;

@ -39,9 +39,7 @@ https://help.fanruan.com/finebi5.1/doc-view-1256.html"
<img src="@/assets/images/caseIcon.png" alt="" /> <img src="@/assets/images/caseIcon.png" alt="" />
<span>案例背景:</span> <span>案例背景:</span>
</div> </div>
<span style="line-height: 25px; font-size: 14px"> <span style="line-height: 25px; font-size: 14px">本案例模拟企业搭建用户的标签系统、用户画像系统,以及用户画像的应用。</span>
本案例模拟企业搭建用户的标签系统、用户画像系统,以及用户画像的应用。
</span>
</div> </div>
<div class="line"></div> <div class="line"></div>
<div class="caseBack"> <div class="caseBack">
@ -50,128 +48,98 @@ https://help.fanruan.com/finebi5.1/doc-view-1256.html"
<span>第一步,获取原始数据</span> <span>第一步,获取原始数据</span>
</div> </div>
<span style="line-height: 25px; font-size: 14px"> <span style="line-height: 25px; font-size: 14px">
用户画像体系依赖于完善的用户标签体系,而用户标签体系则采用完备的数据来源--原始数据,这一层我们需要获得尽量多的原始数据,因后面的所有的应用场景都依托于原始数据的计算、分析、建模,所以在原始数据库搭建时需要考虑更全面。<br /> 用户画像体系依赖于完善的用户标签体系,而用户标签体系则采用完备的数据来源--原始数据,这一层我们需要获得尽量多的原始数据,因后面的所有的应用场景都依托于原始数据的计算、分析、建模,所以在原始数据库搭建时需要考虑更全面。
以电商平台为例,用到用户仓库中的表主要有:用户信息表、商品订单表、商品信息表、App端日志表、Web端日志表、商品评论表等。<br /> <br />
以电商平台为例,用到用户仓库中的表主要有:用户信息表、商品订单表、商品信息表、App端日志表、Web端日志表、商品评论表等。
<br />
请根据字段的相关属性判断该表属于数据库中哪一个? 请根据字段的相关属性判断该表属于数据库中哪一个?
</span> </span>
<div style="margin-top: 10px"> <div style="margin-top: 10px">
<div style="display: flex; margin-bottom: 20px"> <div style="display: flex; margin-bottom: 20px; align-items: center">
<el-select <el-select v-model="step1SelectParams1" placeholder="请选择" style="width: 160px">
v-model="step1SelectParams1" <el-option v-for="item in selectList" :key="item.value" :label="item.label" :value="item.value" />
placeholder="请选择"
style="width: 160px"
>
<el-option
v-for="item in selectList"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select> </el-select>
<div v-if="showAnswerFlag" style="margin-left: 3px; display: inline-block">
<span v-if="step1SelectParams1 != '用户信息表'" style="color: red">X</span>
<span v-if="step1SelectParams1 == '用户信息表'" style="color: #00bb00">√</span>
</div>
<ul class="selectUl"> <ul class="selectUl">
<li class="selectLi" v-for="item in selectTable1" :key="item"> <li class="selectLi" v-for="item in selectTable1" :key="item">
{{ item }} {{ item }}
</li> </li>
</ul> </ul>
</div> </div>
<div style="display: flex; margin-bottom: 20px"> <div style="display: flex; margin-bottom: 20px; align-items: center">
<el-select <el-select v-model="step1SelectParams2" placeholder="请选择" style="width: 160px">
v-model="step1SelectParams2" <el-option v-for="item in selectList" :key="item.value" :label="item.label" :value="item.value" />
placeholder="请选择"
style="width: 160px"
>
<el-option
v-for="item in selectList"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select> </el-select>
<div v-if="showAnswerFlag" style="margin-left: 3px; display: inline-block">
<span v-if="step1SelectParams2 != '商品订单表'" style="color: red">X</span>
<span v-if="step1SelectParams2 == '商品订单表'" style="color: #00bb00">√</span>
</div>
<ul class="selectUl"> <ul class="selectUl">
<li class="selectLi" v-for="item in selectTable2" :key="item"> <li class="selectLi" v-for="item in selectTable2" :key="item">
{{ item }} {{ item }}
</li> </li>
</ul> </ul>
</div> </div>
<div style="display: flex; margin-bottom: 20px"> <div style="display: flex; margin-bottom: 20px; align-items: center">
<el-select <el-select v-model="step1SelectParams3" placeholder="请选择" style="width: 160px">
v-model="step1SelectParams3" <el-option v-for="item in selectList" :key="item.value" :label="item.label" :value="item.value" />
placeholder="请选择"
style="width: 160px"
>
<el-option
v-for="item in selectList"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select> </el-select>
<div v-if="showAnswerFlag" style="margin-left: 3px; display: inline-block">
<span v-if="step1SelectParams3 != '访问日志表'" style="color: red">X</span>
<span v-if="step1SelectParams3 == '访问日志表'" style="color: #00bb00">√</span>
</div>
<ul class="selectUl"> <ul class="selectUl">
<li class="selectLi" v-for="item in selectTable3" :key="item"> <li class="selectLi" v-for="item in selectTable3" :key="item">
{{ item }} {{ item }}
</li> </li>
</ul> </ul>
</div> </div>
<div style="display: flex; margin-bottom: 20px"> <div style="display: flex; margin-bottom: 20px; align-items: center">
<el-select <el-select v-model="step1SelectParams4" placeholder="请选择" style="width: 160px">
v-model="step1SelectParams4" <el-option v-for="item in selectList" :key="item.value" :label="item.label" :value="item.value" />
placeholder="请选择"
style="width: 160px"
>
<el-option
v-for="item in selectList"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select> </el-select>
<div v-if="showAnswerFlag" style="margin-left: 3px; display: inline-block">
<span v-if="step1SelectParams4 != '商品评论表'" style="color: red">X</span>
<span v-if="step1SelectParams4 == '商品评论表'" style="color: #00bb00">√</span>
</div>
<ul class="selectUl"> <ul class="selectUl">
<li class="selectLi" v-for="item in selectTable4" :key="item"> <li class="selectLi" v-for="item in selectTable4" :key="item">
{{ item }} {{ item }}
</li> </li>
</ul> </ul>
</div> </div>
<div style="display: flex; margin-bottom: 20px"> <div style="display: flex; margin-bottom: 20px; align-items: center">
<el-select <el-select v-model="step1SelectParams5" placeholder="请选择" style="width: 160px">
v-model="step1SelectParams5" <el-option v-for="item in selectList" :key="item.value" :label="item.label" :value="item.value" />
placeholder="请选择"
style="width: 160px"
>
<el-option
v-for="item in selectList"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select> </el-select>
<div v-if="showAnswerFlag" style="margin-left: 3px; display: inline-block">
<span v-if="step1SelectParams5 != '搜索日志表'" style="color: red">X</span>
<span v-if="step1SelectParams5 == '搜索日志表'" style="color: #00bb00">√</span>
</div>
<ul class="selectUl"> <ul class="selectUl">
<li class="selectLi" v-for="item in selectTable5" :key="item"> <li class="selectLi" v-for="item in selectTable5" :key="item">
{{ item }} {{ item }}
</li> </li>
</ul> </ul>
</div> </div>
<div style="display: flex; margin-bottom: 20px"> <div style="display: flex; margin-bottom: 20px; align-items: center">
<el-select <el-select v-model="step1SelectParams6" placeholder="请选择" style="width: 160px">
v-model="step1SelectParams6" <el-option v-for="item in selectList" :key="item.value" :label="item.label" :value="item.value" />
placeholder="请选择"
style="width: 160px"
>
<el-option
v-for="item in selectList"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select> </el-select>
<div v-if="showAnswerFlag" style="margin-left: 3px; display: inline-block">
<span v-if="step1SelectParams6 != '销售明细表'" style="color: red">X</span>
<span v-if="step1SelectParams6 == '销售明细表'" style="color: #00bb00">√</span>
</div>
<ul class="selectUl"> <ul class="selectUl">
<li class="selectLi" v-for="item in selectTable6" :key="item"> <li class="selectLi" v-for="item in selectTable6" :key="item">
{{ item }} {{ item }}
</li> </li>
</ul> </ul>
</div> </div>
<div class="submit" style="margin-top: 25px" @click="step1Submit"> <div class="submit" style="margin-top: 25px" @click="step1Submit">提交</div>
提交
</div>
</div> </div>
</div> </div>
<div class="line"></div> <div class="line"></div>
@ -181,10 +149,14 @@ https://help.fanruan.com/finebi5.1/doc-view-1256.html"
<span>第二步,构建用户标签体系</span> <span>第二步,构建用户标签体系</span>
</div> </div>
<span style="line-height: 25px; font-size: 14px"> <span style="line-height: 25px; font-size: 14px">
基于原始数据的转换,文本字段的数量化表示,以及统计汇总,建立属性标签体系。按统计方式分类,可分为事实类标签、规则类标签、预测类标签:<br /> 基于原始数据的转换,文本字段的数量化表示,以及统计汇总,建立属性标签体系。按统计方式分类,可分为事实类标签、规则类标签、预测类标签:
1)事实标签:从原始数据中提取,通常是基于原始数据清理后的归类,用于描述客观事实。例如用户注册信息中提取用户性别、生日、注册手机号、注册城市等。<br /> <br />
2)规则标签:没有直接对应数据,需要通过规则进行定义(可以自定义规则,或者利用常用的RFM、波士顿矩阵、漏斗模型、复购分析、AARRR模型等),通过计算来得出标签,例如流失用户、支付偏好等。<br /> 1)事实标签:从原始数据中提取,通常是基于原始数据清理后的归类,用于描述客观事实。例如用户注册信息中提取用户性别、生日、注册手机号、注册城市等。
3)预测标签:基于现有事实及规则无法得出,需要运用决策树算法、贝叶斯算法等进行数据挖掘与训练,得出标签预测结果,来预测用户的偏好,例如根据用户历史的购买行为来预测其群体特性。<br /> <br />
2)规则标签:没有直接对应数据,需要通过规则进行定义(可以自定义规则,或者利用常用的RFM、波士顿矩阵、漏斗模型、复购分析、AARRR模型等),通过计算来得出标签,例如流失用户、支付偏好等。
<br />
3)预测标签:基于现有事实及规则无法得出,需要运用决策树算法、贝叶斯算法等进行数据挖掘与训练,得出标签预测结果,来预测用户的偏好,例如根据用户历史的购买行为来预测其群体特性。
<br />
不同行业,客户标签体系会有差异,以电商行业为例,常用的标签体系如下表,请对标签进行分类: 不同行业,客户标签体系会有差异,以电商行业为例,常用的标签体系如下表,请对标签进行分类:
</span> </span>
<div style="margin-top: 10px; display: flex"> <div style="margin-top: 10px; display: flex">
@ -199,29 +171,20 @@ https://help.fanruan.com/finebi5.1/doc-view-1256.html"
backgroundColor: '#6A7DE9!important', backgroundColor: '#6A7DE9!important',
}" }"
> >
<el-table-column label="一级标签" align="center" prop="firstTag"> <el-table-column label="一级标签" align="center" prop="firstTag"></el-table-column>
</el-table-column> <el-table-column label="二级标签" align="center" prop="secondTag"></el-table-column>
<el-table-column label="二级标签" align="center" prop="secondTag"> <el-table-column label="三级标签" align="center" prop="thirdTag" width="500"></el-table-column>
</el-table-column> <el-table-column label="标签属性" align="center" prop="description" width="170">
<el-table-column
label="三级标签"
align="center"
prop="thirdTag"
width="500"
>
</el-table-column>
<el-table-column label="标签属性" align="center" prop="description">
<template #default="scope"> <template #default="scope">
<el-select <el-select v-model="scope.row.params" placeholder="请选择" style="width: 130px" size="small">
v-model="scope.row.params"
placeholder="请选择"
style="width: 130px"
size="small"
>
<el-option :label="'事实标签'" :value="'事实标签'" /> <el-option :label="'事实标签'" :value="'事实标签'" />
<el-option :label="'规则标签'" :value="'规则标签'" /> <el-option :label="'规则标签'" :value="'规则标签'" />
<el-option :label="'预测标签'" :value="'预测标签'" /> <el-option :label="'预测标签'" :value="'预测标签'" />
</el-select> </el-select>
<div v-if="showAnswerFlag" style="margin-left: 3px; display: inline-block">
<span v-if="scope.row.isError" style="color: red">X</span>
<span v-if="!scope.row.isError" style="color: #00bb00">√</span>
</div>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
@ -235,9 +198,7 @@ https://help.fanruan.com/finebi5.1/doc-view-1256.html"
<img src="@/assets/images/步骤.png" alt="" /> <img src="@/assets/images/步骤.png" alt="" />
<span>第三步,构建用户画像</span> <span>第三步,构建用户画像</span>
</div> </div>
<span style="line-height: 25px; font-size: 14px"> <span style="line-height: 25px; font-size: 14px">基于构建的用户标签体系,经过数据的采集、预处理、挖掘、可视化,采用文本挖掘算法、分类聚类算法、相似度计算、推荐算法、机器学习算法、预测算法等,以及用户画像分析的各类常用模型(RFM模型、漏斗模型、AARRR模型等),根据不同的业务场景需求,构建相应的用户画像。</span>
基于构建的用户标签体系,经过数据的采集、预处理、挖掘、可视化,采用文本挖掘算法、分类聚类算法、相似度计算、推荐算法、机器学习算法、预测算法等,以及用户画像分析的各类常用模型(RFM模型、漏斗模型、AARRR模型等),根据不同的业务场景需求,构建相应的用户画像。
</span>
<div style="margin-top: 10px; display: flex"> <div style="margin-top: 10px; display: flex">
<div> <div>
<img src="@/assets/images/u6063.png" alt="" /> <img src="@/assets/images/u6063.png" alt="" />
@ -272,18 +233,19 @@ https://help.fanruan.com/finebi5.1/doc-view-1256.html"
<span>第四步,用户画像应用场景</span> <span>第四步,用户画像应用场景</span>
</div> </div>
<span style="line-height: 25px; font-size: 14px"> <span style="line-height: 25px; font-size: 14px">
1、人群分析:人群分析是用户画像最基础的应用场景之一,运营人员可借助标签深入分析不同用户画像群体的分布特征,又或是不同人群的消费习惯、消费偏好、不同地域的差异分析等。<br /> 1、人群分析:人群分析是用户画像最基础的应用场景之一,运营人员可借助标签深入分析不同用户画像群体的分布特征,又或是不同人群的消费习惯、消费偏好、不同地域的差异分析等。
2、广告优化:用户画像可以圈选定位更准确的人群,同时也为素材文案、广告创意提供了更具体的撰写方向,做到精准且有效的投放。此外,用户画像可以助力广告主完成洞察到决策的环节,让投放工作更有目标方向,广告主也可基于标签高效触达目标人群,提升用户体验,实现营销价值的最大化。<br /> <br />
3、精细化消费者运营:运营人员可以通过快速分析用户特征,找到不同运营场景下的目标用户,从而精准圈定目标人群,进行更灵活、更有针对性的营销活动和个性化消息推送。基于用户画像分析,在合适的时间通过最佳渠道,给用户传递最感兴趣的内容。可以根据用户历史数据,实现基于用户兴趣的个性化推荐,也可在文案中植入用户个性化标签,增加用户的好感度亲密度。还可以通过用户历史购买时间,判断用户最容易消费的时间点,在合适时间给用户发送营销信息。<br /> 2、广告优化:用户画像可以圈选定位更准确的人群,同时也为素材文案、广告创意提供了更具体的撰写方向,做到精准且有效的投放。此外,用户画像可以助力广告主完成洞察到决策的环节,让投放工作更有目标方向,广告主也可基于标签高效触达目标人群,提升用户体验,实现营销价值的最大化。
<br />
3、精细化消费者运营:运营人员可以通过快速分析用户特征,找到不同运营场景下的目标用户,从而精准圈定目标人群,进行更灵活、更有针对性的营销活动和个性化消息推送。基于用户画像分析,在合适的时间通过最佳渠道,给用户传递最感兴趣的内容。可以根据用户历史数据,实现基于用户兴趣的个性化推荐,也可在文案中植入用户个性化标签,增加用户的好感度亲密度。还可以通过用户历史购买时间,判断用户最容易消费的时间点,在合适时间给用户发送营销信息。
<br />
</span> </span>
</div> </div>
<div class="line"></div> <div class="line"></div>
</div> </div>
<pop-modal :showModel="dialogVisible" @closePop="dialogVisible = false"> <pop-modal :showModel="dialogVisible" @closePop="dialogVisible = false">
<template v-slot:content> <template v-slot:content>
<div v-html="knowledgeHtml"> <div v-html="knowledgeHtml"></div>
</div>
</template> </template>
</pop-modal> </pop-modal>
</div> </div>
@ -317,6 +279,7 @@ const step1SelectParams3 = ref("");
const step1SelectParams4 = ref(""); const step1SelectParams4 = ref("");
const step1SelectParams5 = ref(""); const step1SelectParams5 = ref("");
const step1SelectParams6 = ref(""); const step1SelectParams6 = ref("");
const showAnswerFlag = ref(false);
const selectList = ref([ const selectList = ref([
{ {
value: "用户信息表", value: "用户信息表",
@ -343,84 +306,12 @@ const selectList = ref([
label: "销售明细表", label: "销售明细表",
}, },
]); ]);
const selectTable1 = ref([ const selectTable1 = ref(["用户编码", "用户姓名", "用户状态", "出生日期", "性别", "电话号码", "注册日期", "归属省", "归属市", "学历", "职业", "行业", "婚姻状况", "子女状况"]);
"用户编码", const selectTable2 = ref(["订单号", "订单来源标识", "用户编码", "用户姓名", "商品编码", "商品名称", "订单生成时间", "订单日期", "订单备注", "订单状态", "订单金额", "付款账户", "付款方式"]);
"用户姓名", const selectTable3 = ref(["设备登录名", "用户ID", "设备ID", "访问时间", "IP所在省份", "IP所在城市", "上一个页面URL", "当前页面URL", "操作系统", "登录日期", "经度", "纬度", "付款方式"]);
"用户状态", const selectTable4 = ref(["用户ID", "用户姓名", "评论内容", "评论图片", "评论状态", "综合评分", "订单ID", "创建日期", "评论用户IP", "更新时间"]);
"出生日期", const selectTable5 = ref(["设备登录名", "用户ID", "设备ID", "搜索ID", "搜索日期", "用户搜索的关键词", "搜索匹配标签内容"]);
"性别", const selectTable6 = ref(["商品编码", "商品名称", "商品归属类目", "销售额", "销售数量", "订单号", "用户编码", "用户姓名", "销售时间"]);
"电话号码",
"注册日期",
"归属省",
"归属市",
"学历",
"职业",
"行业",
"婚姻状况",
"子女状况",
]);
const selectTable2 = ref([
"订单号",
"订单来源标识",
"用户编码",
"用户姓名",
"商品编码",
"商品名称",
"订单生成时间",
"订单日期",
"订单备注",
"订单状态",
"订单金额",
"付款账户",
"付款方式",
]);
const selectTable3 = ref([
"设备登录名",
"用户ID",
"设备ID",
"访问时间",
"IP所在省份",
"IP所在城市",
"上一个页面URL",
"当前页面URL",
"操作系统",
"登录日期",
"经度",
"纬度",
"付款方式",
]);
const selectTable4 = ref([
"用户ID",
"用户姓名",
"评论内容",
"评论图片",
"评论状态",
"综合评分",
"订单ID",
"创建日期",
"评论用户IP",
"更新时间",
]);
const selectTable5 = ref([
"设备登录名",
"用户ID",
"设备ID",
"搜索ID",
"搜索日期",
"用户搜索的关键词",
"搜索匹配标签内容",
]);
const selectTable6 = ref([
"商品编码",
"商品名称",
"商品归属类目",
"销售额",
"销售数量",
"订单号",
"用户编码",
"用户姓名",
"销售时间",
]);
const knowledgeFlag = ref(false); const knowledgeFlag = ref(false);
//时间间隔分组数-7天内 //时间间隔分组数-7天内
const sevenNum = ref(0); const sevenNum = ref(0);
@ -601,8 +492,7 @@ const step2Data = ref([
{ {
firstTag: "用户价值标签", firstTag: "用户价值标签",
secondTag: "用户价值RFM等级", secondTag: "用户价值RFM等级",
thirdTag: thirdTag: "1.重要价值用户;2.重要发展用户;3.重要保持用户;4.重要挽留用户;5.一般价值用户;6.一般发展用户;7.一般保持用户;8.一般挽留用户",
"1.重要价值用户;2.重要发展用户;3.重要保持用户;4.重要挽留用户;5.一般价值用户;6.一般发展用户;7.一般保持用户;8.一般挽留用户",
}, },
{ {
firstTag: "用户价值标签", firstTag: "用户价值标签",
@ -953,22 +843,7 @@ const draw = () => {
}, },
xAxis: { xAxis: {
type: "category", type: "category",
data: [ data: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14"],
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"10",
"11",
"12",
"13",
"14",
],
}, },
yAxis: { yAxis: {
type: "value", type: "value",
@ -1035,14 +910,7 @@ const drawEcharts = () => {
}; };
const step1Submit = () => { const step1Submit = () => {
step1Error.value = 0; step1Error.value = 0;
if ( if (step1SelectParams1.value == "" || step1SelectParams2.value == "" || step1SelectParams3.value == "" || step1SelectParams4.value == "" || step1SelectParams5.value == "" || step1SelectParams6.value == "") {
step1SelectParams1.value == "" ||
step1SelectParams2.value == "" ||
step1SelectParams3.value == "" ||
step1SelectParams4.value == "" ||
step1SelectParams5.value == "" ||
step1SelectParams6.value == ""
) {
proxy.$modal.msgError("请先完成所有填空"); proxy.$modal.msgError("请先完成所有填空");
return; return;
} }
@ -1080,18 +948,27 @@ const step2Submit = () => {
for (let i in sliceList1) { for (let i in sliceList1) {
if (sliceList1[i].params != "事实标签") { if (sliceList1[i].params != "事实标签") {
step2Error.value++; step2Error.value++;
sliceList1[i].isError = true;
} else {
sliceList1[i].isError = false;
} }
} }
let sliceList2 = step2Data.value.slice(29, 34); let sliceList2 = step2Data.value.slice(29, 34);
for (let i in sliceList2) { for (let i in sliceList2) {
if (sliceList2[i].params != "规则标签") { if (sliceList2[i].params != "规则标签") {
step2Error.value++; step2Error.value++;
sliceList2[i].isError = true;
}else{
sliceList2[i].isError = false;
} }
} }
let sliceList3 = step2Data.value.slice(34); let sliceList3 = step2Data.value.slice(34);
for (let i in sliceList3) { for (let i in sliceList3) {
if (sliceList3[i].params != "预测标签") { if (sliceList3[i].params != "预测标签") {
step2Error.value++; step2Error.value++;
sliceList3[i].isError = true;
}else{
sliceList3[i].isError = false;
} }
} }
console.log(step2Error.value, "错误数"); console.log(step2Error.value, "错误数");
@ -1225,9 +1102,11 @@ const submitData = () => {
userId: JSON.parse(getUserInfo()).userId, userId: JSON.parse(getUserInfo()).userId,
taskName: "用户画像分析", taskName: "用户画像分析",
numberOfErrors: errorNum.value, numberOfErrors: errorNum.value,
subState: 1,
}) })
.then((res) => { .then((res) => {
proxy.$modal.msgSuccess("提交成功"); proxy.$modal.msgSuccess("提交成功");
showAnswerFlag.value = true;
}) })
.catch((error) => {}); .catch((error) => {});
}; };
@ -1261,7 +1140,8 @@ defineExpose({
<style scoped lang="scss"> <style scoped lang="scss">
.content { .content {
width: 100%; width: 100%;
background: rgba(0, 29, 64, 0.5); // background: rgba(0, 29, 64, 0.5);
background: #fff;
border: 1px solid #0452c6; border: 1px solid #0452c6;
padding: 10px; padding: 10px;
// opacity: 0.5; // opacity: 0.5;
@ -1286,12 +1166,15 @@ defineExpose({
} }
} }
.caseBack { .caseBack {
color: #000;
.selectUl { .selectUl {
margin: 0; margin: 0;
padding: 0; padding: 0;
margin-left: 20px; margin-left: 20px;
background: #022603; // background: #022603;
border: 1px solid #338554; background: #fdefdd;
// border: 1px solid #338554;
border: 1px solid #f7b55f;
.selectLi { .selectLi {
list-style-type: none; list-style-type: none;
display: inline-block; display: inline-block;
@ -1302,7 +1185,8 @@ defineExpose({
line-height: 28px; line-height: 28px;
text-align: center; text-align: center;
font-size: 14px; font-size: 14px;
border-right: 1px solid #338554; // border-right: 1px solid #338554;
border-right: 1px solid #f7b55f;
} }
.selectLi:nth-last-of-type(1) { .selectLi:nth-last-of-type(1) {
border-right: none; border-right: none;
@ -1557,13 +1441,26 @@ defineExpose({
padding-left: 10px; padding-left: 10px;
} }
} }
// ::v-deep .el-table tr {
// background-color: #002652 !important;
// color: #fff;
// }
// ::v-deep .el-textarea__inner {
// background: #002652;
// color: #fff;
// // color: #5397C3;
// }
::v-deep .el-table tr { ::v-deep .el-table tr {
background-color: #002652 !important; background-color: #fff !important;
color: #fff; color: #000;
}
/* 将悬停背景色改为红色 */
::v-deep .el-table--enable-row-hover .el-table__body tr:hover > td {
background-color: #f5f7fa !important;
} }
::v-deep .el-textarea__inner { ::v-deep .el-textarea__inner {
background: #002652; // background: #002652;
color: #fff; color: #000;
// color: #5397C3; // color: #5397C3;
} }
::v-deep .el-table td { ::v-deep .el-table td {

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -22,16 +22,24 @@ https://blog.csdn.net/kevin1993best/article/details/106329573"
<span>案例背景:</span> <span>案例背景:</span>
</div> </div>
<span style="line-height: 25px; font-size: 14px"> <span style="line-height: 25px; font-size: 14px">
用户粘性分析是一种衡量用户对产品或服务的忠诚度和黏性程度的分析方法。它帮助企业了解用户的行为习惯、使用频率和留存率,以评估用户对产品或服务的依赖程度和忠诚度。用户粘性分析模型通常包括以下指标:活跃用户数、留存率、使用频率、用户转化率、用户流失率。<br /> 用户粘性分析是一种衡量用户对产品或服务的忠诚度和黏性程度的分析方法。它帮助企业了解用户的行为习惯、使用频率和留存率,以评估用户对产品或服务的依赖程度和忠诚度。用户粘性分析模型通常包括以下指标:活跃用户数、留存率、使用频率、用户转化率、用户流失率。
留存率、用户转化率、用户流失率,前面模型已经单独分析过,本实验项目重点分析用户活跃情况。<br /> <br />
常见的用户活跃度统计一段时间内活跃用户的分布情况,如使用了几次、使用了几天、使用了多长时间等。比如一周内用户使用产品的天数分布,使用了 留存率、用户转化率、用户流失率,前面模型已经单独分析过,本实验项目重点分析用户活跃情况。
2 天以上的用户占比,连续使用 7 天的用户人数等。<br /> <br />
在用户粘性分析的指标中,DAU/MAU就是最频繁使用的指标。日活跃用户占月活跃用户的比例越高,表明用户对App的使用粘性越高。<br /> 常见的用户活跃度统计一段时间内活跃用户的分布情况,如使用了几次、使用了几天、使用了多长时间等。比如一周内用户使用产品的天数分布,使用了 2 天以上的用户占比,连续使用 7 天的用户人数等。
日活跃用户(DAU):每天使用产品或服务的独立用户数量。这个指标可以反映产品的日常使用情况。<br /> <br />
周活跃用户(WAU):每周使用产品或服务的独立用户数量。这个指标可以反映产品的周活跃情况。<br /> 在用户粘性分析的指标中,DAU/MAU就是最频繁使用的指标。日活跃用户占月活跃用户的比例越高,表明用户对App的使用粘性越高。
月活跃用户(MAU):每月使用产品或服务的独立用户数量。这个指标可以反映产品的长期使用情况。<br /> <br />
用户粘性通常用DAU/MAU的公式来计算,还有一个公式是每月用户平均活跃天数。DAU即日活跃用户数,MAU即月活跃用户数。<br /> 日活跃用户(DAU):每天使用产品或服务的独立用户数量。这个指标可以反映产品的日常使用情况。
比值越趋近于1表明用户活跃度越高,在比值低于0.2时,应用的传播性和互动性将会很弱。<br /> <br />
周活跃用户(WAU):每周使用产品或服务的独立用户数量。这个指标可以反映产品的周活跃情况。
<br />
月活跃用户(MAU):每月使用产品或服务的独立用户数量。这个指标可以反映产品的长期使用情况。
<br />
用户粘性通常用DAU/MAU的公式来计算,还有一个公式是每月用户平均活跃天数。DAU即日活跃用户数,MAU即月活跃用户数。
<br />
比值越趋近于1表明用户活跃度越高,在比值低于0.2时,应用的传播性和互动性将会很弱。
<br />
下表为某APP用户的登录日志,假设所有用户共计10名。 下表为某APP用户的登录日志,假设所有用户共计10名。
</span> </span>
<div style="margin-top: 10px; display: flex"> <div style="margin-top: 10px; display: flex">
@ -45,26 +53,12 @@ https://blog.csdn.net/kevin1993best/article/details/106329573"
backgroundColor: '#6A7DE9!important', backgroundColor: '#6A7DE9!important',
}" }"
> >
<el-table-column label="用户ID" align="center" prop="id1"> <el-table-column label="用户ID" align="center" prop="id1"></el-table-column>
</el-table-column> <el-table-column label="登录时间" align="center" prop="time1"></el-table-column>
<el-table-column label="登录时间" align="center" prop="time1"> <el-table-column label="登录时长(分钟)" align="center" prop="duration1"></el-table-column>
</el-table-column> <el-table-column label="用户ID" align="center" prop="id2"></el-table-column>
<el-table-column <el-table-column label="登录时间" align="center" prop="time2"></el-table-column>
label="登录时长(分钟)" <el-table-column label="登录时长(分钟)" align="center" prop="duration2"></el-table-column>
align="center"
prop="duration1"
>
</el-table-column>
<el-table-column label="用户ID" align="center" prop="id2">
</el-table-column>
<el-table-column label="登录时间" align="center" prop="time2">
</el-table-column>
<el-table-column
label="登录时长(分钟)"
align="center"
prop="duration2"
>
</el-table-column>
</el-table> </el-table>
<div class="download" @click="downloadData">下载数据</div> <div class="download" @click="downloadData">下载数据</div>
</div> </div>
@ -76,15 +70,17 @@ https://blog.csdn.net/kevin1993best/article/details/106329573"
<span>第一步,日活跃用户分析</span> <span>第一步,日活跃用户分析</span>
</div> </div>
<span style="line-height: 25px; font-size: 14px"> <span style="line-height: 25px; font-size: 14px">
日活跃用户(DAU):每天使用产品或服务的独立用户数量。这个指标可以反映产品的日常使用情况。分析近一个月日活跃用户变动情况,包括变动率。这个时候统计活跃用户需要进行去重,一天活跃多次的只保留一条记录。<br /> 日活跃用户(DAU):每天使用产品或服务的独立用户数量。这个指标可以反映产品的日常使用情况。分析近一个月日活跃用户变动情况,包括变动率。这个时候统计活跃用户需要进行去重,一天活跃多次的只保留一条记录。
<br />
日活跃率 = 去重后的日活跃用户数量 / 历史累计去重后的用户数量*100% 日活跃率 = 去重后的日活跃用户数量 / 历史累计去重后的用户数量*100%
<br /> <br />
日活跃平均时长=登录时长/活跃用户数,计算结果保留小数点后两位 <br /> 日活跃平均时长=登录时长/活跃用户数,计算结果保留小数点后两位
<br />
</span> </span>
<div style="margin-top: 10px; display: flex"> <div style="margin-top: 10px; display: flex">
<el-table <el-table
:data="step1Data" :data="step1Data"
style="width: 600px" style="width: 650px"
border border
:header-cell-style="{ :header-cell-style="{
color: '#fff', color: '#fff',
@ -92,69 +88,41 @@ https://blog.csdn.net/kevin1993best/article/details/106329573"
backgroundColor: '#6A7DE9!important', backgroundColor: '#6A7DE9!important',
}" }"
> >
<el-table-column label="登录时间" align="center" prop="date"> <el-table-column label="登录时间" align="center" prop="date"></el-table-column>
</el-table-column> <el-table-column label="日活跃用户(个)" align="center" prop="addNum">
<el-table-column
label="日活跃用户(个)"
align="center"
prop="addNum"
>
<template #default="scope"> <template #default="scope">
<el-input <el-input v-model="scope.row.params1" placeholder="请输入" style="width: 90px" size="small"></el-input>
v-model="scope.row.params1" <div v-if="showAnswerFlag" style="margin-left: 3px; display: inline-block">
placeholder="请输入" <span v-if="scope.row.isError1" style="color: red">X</span>
style="width: 90px" <span v-if="!scope.row.isError1" style="color: #00bb00">√</span>
size="small" </div>
>
</el-input>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="日活跃率(%)" align="center" prop="day2"> <el-table-column label="日活跃率(%)" align="center" prop="day2" width="150">
<template #default="scope"> <template #default="scope">
<el-input <el-input v-model="scope.row.params2" placeholder="请输入" style="width: 90px" size="small"></el-input>
v-model="scope.row.params2" %
placeholder="请输入" <div v-if="showAnswerFlag" style="margin-left: 3px; display: inline-block">
style="width: 90px" <span v-if="scope.row.isError2" style="color: red">X</span>
size="small" <span v-if="!scope.row.isError2" style="color: #00bb00">√</span>
> </div>
</el-input
>%
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column label="日活跃平均时长(分钟)" align="center" prop="day3" width="180">
label="日活跃平均时长(分钟)"
align="center"
prop="day3"
width="180"
>
<template #default="scope"> <template #default="scope">
<el-input <el-input v-model="scope.row.params3" placeholder="请输入" style="width: 90px" size="small"></el-input>
v-model="scope.row.params3" <div v-if="showAnswerFlag" style="margin-left: 3px; display: inline-block">
placeholder="请输入" <span v-if="scope.row.isError3" style="color: red">X</span>
style="width: 90px" <span v-if="!scope.row.isError3" style="color: #00bb00">√</span>
size="small" </div>
>
</el-input>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
<div> <div>
<div <div class="draw" style="padding-left: 15px; margin-left: 20px" @click="drawEcharts">绘制图表</div>
class="draw"
style="padding-left: 15px; margin-left: 20px"
@click="drawEcharts"
>
绘制图表
</div>
<div id="echartsDom" style="width: 750px; height: 500px"></div> <div id="echartsDom" style="width: 750px; height: 500px"></div>
<div class="analysisConclusion">分析结论</div> <div class="analysisConclusion">分析结论</div>
<el-input <el-input v-model="analysisConclusionStep1" style="margin-left: 20px; margin-top: 20px; margin-bottom: 20px" :rows="12" type="textarea" placeholder="请输入" />
v-model="analysisConclusionStep1"
style="margin-left: 20px; margin-top: 20px; margin-bottom: 20px"
:rows="12"
type="textarea"
placeholder="请输入"
/>
<div class="submit" @click="step1Submit">提交</div> <div class="submit" @click="step1Submit">提交</div>
</div> </div>
</div> </div>
@ -166,7 +134,8 @@ https://blog.csdn.net/kevin1993best/article/details/106329573"
<span>第二步,周活跃用户分析</span> <span>第二步,周活跃用户分析</span>
</div> </div>
<span style="line-height: 25px; font-size: 14px"> <span style="line-height: 25px; font-size: 14px">
周活跃用户(WAU):每周使用产品或服务的独立用户数量。这个指标可以反映产品的周活跃情况。<br /> 周活跃用户(WAU):每周使用产品或服务的独立用户数量。这个指标可以反映产品的周活跃情况。
<br />
周活跃率 = 去重后的周活跃用户数量 / 历史累计去重后的用户数量*100% 周活跃率 = 去重后的周活跃用户数量 / 历史累计去重后的用户数量*100%
</span> </span>
@ -181,49 +150,31 @@ https://blog.csdn.net/kevin1993best/article/details/106329573"
backgroundColor: '#6A7DE9!important', backgroundColor: '#6A7DE9!important',
}" }"
> >
<el-table-column label="周数" align="center" prop="week"> <el-table-column label="周数" align="center" prop="week"></el-table-column>
</el-table-column> <el-table-column label="日期间隔" align="center" prop="interval"></el-table-column>
<el-table-column label="日期间隔" align="center" prop="interval"> <el-table-column label="周活跃用户(个)" align="center" prop="description">
</el-table-column>
<el-table-column
label="周活跃用户(个)"
align="center"
prop="description"
>
<template #default="scope"> <template #default="scope">
<el-input <el-input v-model="scope.row.params1" placeholder="请输入" style="width: 90px"></el-input>
v-model="scope.row.params1" <div v-if="showAnswerFlag" style="margin-left: 3px; display: inline-block">
placeholder="请输入" <span v-if="scope.row.isError1" style="color: red">X</span>
style="width: 90px" <span v-if="!scope.row.isError1" style="color: #00bb00">√</span>
> </div>
</el-input>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column label="周活跃率(%)" align="center" prop="description">
label="周活跃率(%)"
align="center"
prop="description"
>
<template #default="scope"> <template #default="scope">
<el-input <el-input v-model="scope.row.params2" placeholder="请输入" style="width: 90px"></el-input>
v-model="scope.row.params2" %
placeholder="请输入" <div v-if="showAnswerFlag" style="margin-left: 3px; display: inline-block">
style="width: 90px" <span v-if="scope.row.isError2" style="color: red">X</span>
> <span v-if="!scope.row.isError2" style="color: #00bb00">√</span>
</el-input </div>
>%
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
<div style="width: 650px"> <div style="width: 650px">
<div class="analysisConclusion">分析结论</div> <div class="analysisConclusion">分析结论</div>
<el-input <el-input v-model="analysisConclusionStep2" style="margin-left: 20px; margin-top: 20px; margin-bottom: 20px" :rows="8" type="textarea" placeholder="请输入" />
v-model="analysisConclusionStep2"
style="margin-left: 20px; margin-top: 20px; margin-bottom: 20px"
:rows="8"
type="textarea"
placeholder="请输入"
/>
<div class="submit" @click="step2Submit">提交</div> <div class="submit" @click="step2Submit">提交</div>
</div> </div>
</div> </div>
@ -234,9 +185,7 @@ https://blog.csdn.net/kevin1993best/article/details/106329573"
<img src="@/assets/images/步骤.png" alt="" /> <img src="@/assets/images/步骤.png" alt="" />
<span>第三步,月活跃用户分析</span> <span>第三步,月活跃用户分析</span>
</div> </div>
<span style="line-height: 25px; font-size: 14px"> <span style="line-height: 25px; font-size: 14px">月活跃用户(MAU):每月使用产品或服务的独立用户数量。这个指标可以反映产品的长期使用情况。</span>
月活跃用户(MAU):每月使用产品或服务的独立用户数量。这个指标可以反映产品的长期使用情况。
</span>
<div style="margin-top: 10px; display: flex"> <div style="margin-top: 10px; display: flex">
<el-table <el-table
:data="step3Data" :data="step3Data"
@ -248,47 +197,30 @@ https://blog.csdn.net/kevin1993best/article/details/106329573"
backgroundColor: '#6A7DE9!important', backgroundColor: '#6A7DE9!important',
}" }"
> >
<el-table-column label="月份" align="center" prop="month"> <el-table-column label="月份" align="center" prop="month"></el-table-column>
</el-table-column> <el-table-column label="月活跃用户(个)" align="center" prop="description">
<el-table-column
label="月活跃用户(个)"
align="center"
prop="description"
>
<template #default="scope"> <template #default="scope">
<el-input <el-input v-model="scope.row.params1" placeholder="请输入" style="width: 90px"></el-input>
v-model="scope.row.params1" <div v-if="showAnswerFlag" style="margin-left: 3px; display: inline-block">
placeholder="请输入" <span v-if="scope.row.isError1" style="color: red">X</span>
style="width: 90px" <span v-if="!scope.row.isError1" style="color: #00bb00">√</span>
> </div>
</el-input>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column label="月活跃率(%)" align="center" prop="description">
label="月活跃率(%)"
align="center"
prop="description"
>
<template #default="scope"> <template #default="scope">
<el-input <el-input v-model="scope.row.params2" placeholder="请输入" style="width: 90px"></el-input>
v-model="scope.row.params2" %
placeholder="请输入" <div v-if="showAnswerFlag" style="margin-left: 3px; display: inline-block">
style="width: 90px" <span v-if="scope.row.isError2" style="color: red">X</span>
> <span v-if="!scope.row.isError2" style="color: #00bb00">√</span>
</el-input </div>
>%
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
<div style="width: 650px"> <div style="width: 650px">
<div class="analysisConclusion">分析结论</div> <div class="analysisConclusion">分析结论</div>
<el-input <el-input v-model="analysisConclusionStep3" style="margin-left: 20px; margin-top: 20px; margin-bottom: 20px" :rows="8" type="textarea" placeholder="请输入" />
v-model="analysisConclusionStep3"
style="margin-left: 20px; margin-top: 20px; margin-bottom: 20px"
:rows="8"
type="textarea"
placeholder="请输入"
/>
<div class="submit" @click="step3Submit">提交</div> <div class="submit" @click="step3Submit">提交</div>
</div> </div>
</div> </div>
@ -304,25 +236,14 @@ https://blog.csdn.net/kevin1993best/article/details/106329573"
<div>比率指标1- DAU/MAU</div> <div>比率指标1- DAU/MAU</div>
<div style="display: flex; align-items: center"> <div style="display: flex; align-items: center">
<span>通过用户粘性指标定义为过去一天的比过去30天的</span> <span>通过用户粘性指标定义为过去一天的比过去30天的</span>
<img <img src="@/assets/images/u5627.png" alt="" style="margin-left: 10px" />
src="@/assets/images/u5627.png"
alt=""
style="margin-left: 10px"
/>
</div> </div>
</div> </div>
<div style="font-size: 14px"> <div style="font-size: 14px">
<div>比率指标2 - 月平均活跃天数</div> <div>比率指标2 - 月平均活跃天数</div>
<div style="display: flex; align-items: center"> <div style="display: flex; align-items: center">
<span <span>分子可理解为过去30天用户的总活跃天数,分母为过去30天活跃用户数 ,分子/分母 即为 过去30天的人均活跃天数</span>
>分子可理解为过去30天用户的总活跃天数,分母为过去30天活跃用户数 <img src="@/assets/images/u5626.png" alt="" style="margin-left: 10px" />
,分子/分母 即为 过去30天的人均活跃天数</span
>
<img
src="@/assets/images/u5626.png"
alt=""
style="margin-left: 10px"
/>
</div> </div>
</div> </div>
<div style="margin-top: 10px; display: flex"> <div style="margin-top: 10px; display: flex">
@ -336,16 +257,14 @@ https://blog.csdn.net/kevin1993best/article/details/106329573"
backgroundColor: '#6A7DE9!important', backgroundColor: '#6A7DE9!important',
}" }"
> >
<el-table-column label="用户ID" align="center" prop="id"> <el-table-column label="用户ID" align="center" prop="id"></el-table-column>
</el-table-column>
<el-table-column label="活跃天数" align="center" prop="data1"> <el-table-column label="活跃天数" align="center" prop="data1">
<template #default="scope"> <template #default="scope">
<el-input <el-input v-model="scope.row.params1" placeholder="请输入" style="width: 90px"></el-input>
v-model="scope.row.params1" <div v-if="showAnswerFlag" style="margin-left: 3px; display: inline-block">
placeholder="请输入" <span v-if="scope.row.isError" style="color: red">X</span>
style="width: 90px" <span v-if="!scope.row.isError" style="color: #00bb00">√</span>
> </div>
</el-input>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
@ -359,39 +278,44 @@ https://blog.csdn.net/kevin1993best/article/details/106329573"
backgroundColor: '#6A7DE9!important', backgroundColor: '#6A7DE9!important',
}" }"
> >
<el-table-column label="比率指标" align="center" prop="id"> <el-table-column label="比率指标" align="center" prop="id"></el-table-column>
</el-table-column>
<el-table-column label="数值" align="center" prop="data1"> <el-table-column label="数值" align="center" prop="data1">
<template #default="scope"> <template #default="scope">
<el-input <el-input v-model="scope.row.params1" placeholder="请输入" style="width: 90px"></el-input>
v-model="scope.row.params1" <div v-if="showAnswerFlag" style="margin-left: 3px; display: inline-block">
placeholder="请输入" <span v-if="scope.row.isError" style="color: red">X</span>
style="width: 90px" <span v-if="!scope.row.isError" style="color: #00bb00">√</span>
> </div>
</el-input>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
<div style="width: 650px"> <div style="width: 650px">
<div class="analysisConclusion">分析结论</div> <div class="analysisConclusion">分析结论</div>
<el-input <el-input v-model="analysisConclusionStep4" style="margin-left: 20px; margin-top: 20px; margin-bottom: 20px" :rows="8" type="textarea" placeholder="请输入" />
v-model="analysisConclusionStep4"
style="margin-left: 20px; margin-top: 20px; margin-bottom: 20px"
:rows="8"
type="textarea"
placeholder="请输入"
/>
<div class="submit" @click="step4Submit">提交</div> <div class="submit" @click="step4Submit">提交</div>
</div> </div>
</div> </div>
</div> </div>
<div class="line"></div> <div class="line"></div>
<div>
<span style="line-height: 25px; font-size: 14px; color: #000">
DAU/MAU比值越趋近于1表明用户活跃度越高,在比值低于0.2时,应用的传播性和互动性将会很弱。对于常见的App,用户粘性的取值范围就是3%~100%,不同领域的App也会有不同的基准值,例如移动游戏会以20%为基线,而工具类App会以40%为基线。
<br />
例子1: 从极限的角度看,如果每天活跃都是同样的用户,例如每天都是1万DAU,那么30天内每天都是这1万用户在活跃,MAU也是1万,于是DAU/MAU就是100%,用户粘性达到上限,微信就是接近100%的例子。
<br />
例子2: 另一个极端的例子,如果每天活跃用户都不相同,例如每天1万DAU,那么30天内每天的活跃用户都不同,MAU就是30万,于是DAU/MAU就是1/30,用户完全没有粘性。
<br />
在日常的项目和产品运营工作中, 单日的DAU/MAU的数值往往受到周期(工作日/周末)、版本更新和活动的影响,用户粘性在短期内的波动较大。所以通常要采用长期的均值作参考,例如一个月、两个大版本之间。eg:以某客户App为例,DAU/MAU的数值在工作日约50%,而在周末和假期的数值则在20%左右。那么谈到用户粘性的时候,通常采用每天DAU/MAU的平均值39.37%。
</span>
</div>
<div class="line"></div>
</div> </div>
<pop-modal :showModel="dialogVisible" @closePop="dialogVisible = false"> <pop-modal :showModel="dialogVisible" @closePop="dialogVisible = false">
<template v-slot:content> <template v-slot:content>
<div v-html="knowledgeHtml"> <div v-html="knowledgeHtml"></div>
</div>
</template> </template>
</pop-modal> </pop-modal>
</div> </div>
@ -428,6 +352,7 @@ const step2Error = ref(0);
const step3Error = ref(0); const step3Error = ref(0);
const step4Error = ref(0); const step4Error = ref(0);
const knowledgeFlag = ref(false); const knowledgeFlag = ref(false);
const showAnswerFlag = ref(false);
//时间间隔分组数-7天内 //时间间隔分组数-7天内
const sevenNum = ref(0); const sevenNum = ref(0);
//时间间隔分组数-15天内 //时间间隔分组数-15天内
@ -1313,18 +1238,7 @@ const step2RightAnswer = ref([
ratio: "60", ratio: "60",
}, },
]); ]);
const step4RightAnswer = ref([ const step4RightAnswer = ref(["6", "10", "11", "13", "2", "5", "3", "5", "1", "4"]);
"6",
"10",
"11",
"13",
"2",
"5",
"3",
"5",
"1",
"4",
]);
onMounted(() => { onMounted(() => {
getData(); getData();
}); });
@ -1424,22 +1338,7 @@ const draw = () => {
}, },
xAxis: { xAxis: {
type: "category", type: "category",
data: [ data: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14"],
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"10",
"11",
"12",
"13",
"14",
],
}, },
yAxis: { yAxis: {
type: "value", type: "value",
@ -1460,11 +1359,7 @@ const draw = () => {
const drawEcharts = () => { const drawEcharts = () => {
for (let i in step1Data.value) { for (let i in step1Data.value) {
console.log(step1Data.value[i]); console.log(step1Data.value[i]);
if ( if (!step1Data.value[i].params1 || !step1Data.value[i].params2 || !step1Data.value[i].params3) {
!step1Data.value[i].params1 ||
!step1Data.value[i].params2 ||
!step1Data.value[i].params3
) {
proxy.$modal.msgError("请完成所有填空数据"); proxy.$modal.msgError("请完成所有填空数据");
return; return;
} }
@ -1575,11 +1470,7 @@ const step1Submit = () => {
step1Error.value = 0; step1Error.value = 0;
for (let i in step1Data.value) { for (let i in step1Data.value) {
// console.log(fileTable1.value[i]); // console.log(fileTable1.value[i]);
if ( if (!step1Data.value[i].params1 || !step1Data.value[i].params2 || !step1Data.value[i].params3) {
!step1Data.value[i].params1 ||
!step1Data.value[i].params2 ||
!step1Data.value[i].params3
) {
proxy.$modal.msgError("请先完成所有填空"); proxy.$modal.msgError("请先完成所有填空");
return; return;
} }
@ -1587,12 +1478,21 @@ const step1Submit = () => {
for (let i in step1Data.value) { for (let i in step1Data.value) {
if (step1Data.value[i].params1 != step1RightAnswer.value[i].activeNum) { if (step1Data.value[i].params1 != step1RightAnswer.value[i].activeNum) {
step1Error.value++; step1Error.value++;
step1Data.value[i].isError1 = true;
} else {
step1Data.value[i].isError1 = false;
} }
if (step1Data.value[i].params2 != step1RightAnswer.value[i].activeRate) { if (step1Data.value[i].params2 != step1RightAnswer.value[i].activeRate) {
step1Error.value++; step1Error.value++;
step1Data.value[i].isError2 = true;
} else {
step1Data.value[i].isError2 = false;
} }
if (step1Data.value[i].params3 != step1RightAnswer.value[i].activeTime) { if (step1Data.value[i].params3 != step1RightAnswer.value[i].activeTime) {
step1Error.value++; step1Error.value++;
step1Data.value[i].isError3 = true;
} else {
step1Data.value[i].isError3 = false;
} }
} }
console.log(step1Error.value, "错误数"); console.log(step1Error.value, "错误数");
@ -1611,9 +1511,15 @@ const step2Submit = () => {
for (let i in step2Data.value) { for (let i in step2Data.value) {
if (step2Data.value[i].params1 != step2RightAnswer.value[i].num) { if (step2Data.value[i].params1 != step2RightAnswer.value[i].num) {
step2Error.value++; step2Error.value++;
step2Data.value[i].isError1 = true;
} else {
step2Data.value[i].isError1 = false;
} }
if (step2Data.value[i].params2 != step2RightAnswer.value[i].ratio) { if (step2Data.value[i].params2 != step2RightAnswer.value[i].ratio) {
step2Error.value++; step2Error.value++;
step2Data.value[i].isError2 = true;
} else {
step2Data.value[i].isError2 = false;
} }
} }
console.log(step2Error.value, "错误数"); console.log(step2Error.value, "错误数");
@ -1631,9 +1537,15 @@ const step3Submit = () => {
} }
if (step3Data.value[0].params1 != "10") { if (step3Data.value[0].params1 != "10") {
step3Error.value++; step3Error.value++;
step3Data.value[0].isError1 = true;
}else{
step3Data.value[0].isError1 = false;
} }
if (step3Data.value[0].params2 != "100") { if (step3Data.value[0].params2 != "100") {
step3Error.value++; step3Error.value++;
step3Data.value[0].isError2 = true;
}else{
step3Data.value[0].isError2 = false;
} }
// console.log(89); // console.log(89);
console.log(step3Error.value, "错误数"); console.log(step3Error.value, "错误数");
@ -1659,13 +1571,22 @@ const step4Submit = () => {
for (let i in step4Data.value) { for (let i in step4Data.value) {
if (step4Data.value[i].params1 != step4RightAnswer.value[i]) { if (step4Data.value[i].params1 != step4RightAnswer.value[i]) {
step4Error.value++; step4Error.value++;
step4Data.value[i].isError = true;
}else{
step4Data.value[i].isError = false;
} }
} }
if (step4DataTable2.value[0].params1 != "20") { if (step4DataTable2.value[0].params1 != "20") {
step4Error.value++; step4Error.value++;
step4DataTable2.value[0].isError = true;
}else{
step4DataTable2.value[0].isError = false;
} }
if (step4DataTable2.value[1].params1 != "3") { if (step4DataTable2.value[1].params1 != "3") {
step4Error.value++; step4Error.value++;
step4DataTable2.value[1].isError = true;
}else{
step4DataTable2.value[1].isError = false;
} }
console.log(step4Error.value, "错误数"); console.log(step4Error.value, "错误数");
proxy.$modal.msgSuccess("提交成功"); proxy.$modal.msgSuccess("提交成功");
@ -1747,16 +1668,10 @@ const getData = () => {
}) })
.then((res) => { .then((res) => {
for (let i in res.data.stuMachineLearningInfoDTOList) { for (let i in res.data.stuMachineLearningInfoDTOList) {
if ( if (res.data.stuMachineLearningInfoDTOList[i].loginTime == step1Data.value[i].date) {
res.data.stuMachineLearningInfoDTOList[i].loginTime == step1Data.value[i].params1 = res.data.stuMachineLearningInfoDTOList[i].activeUser;
step1Data.value[i].date step1Data.value[i].params2 = res.data.stuMachineLearningInfoDTOList[i].activeUserRate;
) { step1Data.value[i].params3 = res.data.stuMachineLearningInfoDTOList[i].activeUserTime;
step1Data.value[i].params1 =
res.data.stuMachineLearningInfoDTOList[i].activeUser;
step1Data.value[i].params2 =
res.data.stuMachineLearningInfoDTOList[i].activeUserRate;
step1Data.value[i].params3 =
res.data.stuMachineLearningInfoDTOList[i].activeUserTime;
} }
} }
step2Data.value[0].params1 = res.data.stepFiveA; step2Data.value[0].params1 = res.data.stepFiveA;
@ -1820,26 +1735,22 @@ const downloadData = () => {
window.open(baseUrl + "/api/downDataByUserPortrait/analysisByStickiness"); window.open(baseUrl + "/api/downDataByUserPortrait/analysisByStickiness");
}; };
const submitData = () => { const submitData = () => {
if ( if (!step1AnswerFlag.value || !step2AnswerFlag.value || !step3AnswerFlag.value || !step4AnswerFlag.value) {
!step1AnswerFlag.value ||
!step2AnswerFlag.value ||
!step3AnswerFlag.value ||
!step4AnswerFlag.value
) {
proxy.$modal.msgError("请先完成所有步骤!"); proxy.$modal.msgError("请先完成所有步骤!");
return; return;
} }
errorNum.value = errorNum.value = step1Error.value + step2Error.value + step3Error.value + step4Error.value;
step1Error.value + step2Error.value + step3Error.value + step4Error.value;
console.log(errorNum.value, "总错误次数"); console.log(errorNum.value, "总错误次数");
portraitModel portraitModel
.submit({ .submit({
userId: JSON.parse(getUserInfo()).userId, userId: JSON.parse(getUserInfo()).userId,
taskName: "用户粘性分析", taskName: "用户粘性分析",
numberOfErrors: errorNum.value, numberOfErrors: errorNum.value,
subState: 1,
}) })
.then((res) => { .then((res) => {
proxy.$modal.msgSuccess("提交成功"); proxy.$modal.msgSuccess("提交成功");
showAnswerFlag.value = true;
}) })
.catch((error) => {}); .catch((error) => {});
}; };
@ -1889,7 +1800,8 @@ defineExpose({
<style scoped lang="scss"> <style scoped lang="scss">
.content { .content {
width: 100%; width: 100%;
background: rgba(0, 29, 64, 0.5); // background: rgba(0, 29, 64, 0.5);
background: #fff;
border: 1px solid #0452c6; border: 1px solid #0452c6;
padding: 10px; padding: 10px;
// opacity: 0.5; // opacity: 0.5;
@ -1914,6 +1826,7 @@ defineExpose({
} }
} }
.caseBack { .caseBack {
color: #000;
.title { .title {
font-weight: bold; font-weight: bold;
margin-top: 10px; margin-top: 10px;
@ -2064,13 +1977,21 @@ defineExpose({
padding-left: 10px; padding-left: 10px;
} }
} }
// ::v-deep .el-table tr {
// background-color: #002652 !important;
// color: #fff;
// }
::v-deep .el-table tr { ::v-deep .el-table tr {
background-color: #002652 !important; background-color: #fff !important;
color: #fff; color: #000;
}
/* 将悬停背景色改为红色 */
::v-deep .el-table--enable-row-hover .el-table__body tr:hover > td {
background-color: #f5f7fa !important;
} }
::v-deep .el-textarea__inner { ::v-deep .el-textarea__inner {
background: #002652; // background: #002652;
color: #fff; color: #000;
// color: #5397C3; // color: #5397C3;
} }
::v-deep .el-table td { ::v-deep .el-table td {

Loading…
Cancel
Save