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

1563 lines
50 KiB
Vue

<template>
<div class="content">
2 years ago
<div class="import" @click="dialogVisible = true">
<img src="@/assets/images/导入.png" alt="" />
<span>任务知识导入</span>
</div>
2 years ago
<!-- <div v-if="knowledgeFlag">
<p style="line-height: 25px; font-size: 14px">
波士顿矩阵BCG
Matrix又称市场增长率-相对市场份额矩阵由美国著名的管理学家波士顿咨询公司创始人布鲁斯·亨德森于1970年首创它是通过销售增长率反应市场引力的指标和市场占有率反应企业实力的指标来分析决定企业的产品结构<br />
市场吸引力包括企业销售量增长率目标市场容量竞争对手强弱利润高低等其中最重要的是反映市场引力的综合指标销售增长率这是决定企业产品结构是否合理的外在因素<br />
企业实力包括市场占有率技术设备资金利用能力等其中市场占有率是决定企业产品结构的内在因素他直接显示出企业的竞争实力
</p>
<img src="@/assets/images/u3678.png" alt="" /><br />
<span style="line-height: 25px; font-size: 14px">
波士顿矩阵将产品类型分为四种<br />
1明星类产品高增长且高市占发展前景好竞争力强需加大投资以支持其发展<br />
2问题类产品高增长但低市占发展前景好但市场开拓不足需谨慎投资<br />
3现金牛产品低增长但高市占成熟市场的领导者应降低投资维持市占并延缓衰退<br />
4瘦狗类产品低增长且低市占理论率低甚至亏损应采取撤退战略 </span
><br />
<img src="@/assets/images/u3682.png" alt="" />
2 years ago
</div> -->
<div>
<div class="caseBack">
<div class="title">
<img src="@/assets/images/caseIcon.png" alt="" />
<span>案例背景</span>
</div>
2 years ago
<span style="line-height: 25px; font-size: 14px">现有以下某商店的客户消费原始数据需要采用波士顿矩阵分析方法对客户进行分类</span>
<div style="margin-top: 10px; display: flex">
<el-table
:data="fileTable1"
style="width: 650px"
border
:header-cell-style="{
color: '#fff',
fontSize: '14px',
backgroundColor: '#6A7DE9!important',
}"
>
2 years ago
<el-table-column label="客户ID" align="center" prop="id"></el-table-column>
<el-table-column label="消费金额" align="center" prop="amount"></el-table-column>
<el-table-column label="消费时间" align="center" prop="time"></el-table-column>
</el-table>
2 years ago
<div class="download" @click="downloadData"></div>
</div>
</div>
<div class="line"></div>
<div class="caseBack">
<div class="title">
<img src="@/assets/images/步骤.png" alt="" />
<span>第一步统计各个客户的消费次数和消费金额</span>
</div>
2 years ago
<span style="line-height: 25px; font-size: 14px">以客户ID为统计单元分别计算各个客户累计的消费次数消费金额</span>
<div style="margin-top: 10px; display: flex">
<el-table
:data="step1Data"
style="width: 550px"
border
:header-cell-style="{
color: '#fff',
fontSize: '14px',
backgroundColor: '#6A7DE9!important',
}"
>
2 years ago
<el-table-column label="客户ID" align="center" prop="name"></el-table-column>
<el-table-column label="消费次数" align="center" prop="amount">
<template #default="scope">
2 years ago
<el-input v-model="scope.row.params1" placeholder="请输入" style="width: 130px"></el-input>
</template>
</el-table-column>
<el-table-column label="消费金额" align="center" prop="amount">
<template #default="scope">
2 years ago
<el-input v-model="scope.row.params2" placeholder="请输入" style="width: 130px"></el-input>
</template>
</el-table-column>
</el-table>
<div class="submit" @click="step1Submit"></div>
</div>
</div>
<div class="line"></div>
<div class="caseBack">
<div class="title">
<img src="@/assets/images/步骤.png" alt="" />
<span>第二步确定象限测度划分标准</span>
</div>
2 years ago
<span style="line-height: 25px; font-size: 14px">以客户ID为统计单元分别计算各个客户的平均消费次数平均消费金额</span>
2 years ago
<div style="margin-top: 10px; display: flex" v-if="step1AnswerFlag">
<el-table
:data="step2Data"
style="width: 650px"
border
:header-cell-style="{
color: '#fff',
fontSize: '14px',
backgroundColor: '#6A7DE9!important',
}"
>
2 years ago
<el-table-column label="客户ID" align="center" prop="name"></el-table-column>
<el-table-column label="消费次数" align="center" prop="amount">
<template #default="scope">
2 years ago
<el-input v-model="scope.row.params1" placeholder="请输入" style="width: 130px" v-if="scope.$index == 4"></el-input>
</template>
</el-table-column>
<el-table-column label="消费金额" align="center" prop="account">
<template #default="scope">
2 years ago
<el-input v-model="scope.row.params2" placeholder="请输入" style="width: 130px" v-if="scope.$index == 4"></el-input>
</template>
</el-table-column>
</el-table>
<div class="submit" @click="step2Submit"></div>
</div>
</div>
<div class="line"></div>
<div class="caseBack">
<div class="title">
<img src="@/assets/images/步骤.png" alt="" />
<span>第三步绘制散点图</span>
</div>
2 years ago
<span style="line-height: 25px; font-size: 14px">以消费金额为纵轴消费次数为横轴将第一步的客户数据绘制于坐标轴中</span>
<div style="margin-top: 10px; display: flex">
<div id="charts1" style="width: 500px; height: 400px"></div>
<div>
<div class="submit" @click="step3Submit"></div>
<div class="drawPoint">
<div class="point">
2 years ago
<div class="pointItem" @click="drawPoint('A', '#009FF1')">绘制A</div>
<span>3,800</span>
</div>
<div class="point">
2 years ago
<div class="pointItem" @click="drawPoint('B', '#FB54A1')">绘制B</div>
<span>4,1200</span>
</div>
<div class="point">
2 years ago
<div class="pointItem" @click="drawPoint('C', '#FE8D2A')">绘制C</div>
<span>6,600</span>
</div>
<div class="point">
2 years ago
<div class="pointItem" @click="drawPoint('D', '#6E70F0')">绘制D</div>
<span>7,1400</span>
</div>
</div>
</div>
</div>
</div>
<div class="line"></div>
<div class="caseBack">
<div class="title">
<img src="@/assets/images/步骤.png" alt="" />
<span>第四步坐标轴区域绘制象限测度划分标准</span>
</div>
2 years ago
<span style="line-height: 25px; font-size: 14px">将计算出的客户的平均消费次数平均消费金额绘制在坐标轴中</span>
<div style="margin-top: 10px; display: flex">
<div id="charts2" style="width: 500px; height: 400px"></div>
<div>
<div class="submit" @click="step4Submit"></div>
<div class="drawPoint">
<div class="point">
<div class="pointItem" @click="drawPointStep4('E', '#009FF1')">绘制平均消费次数X,平均消费金额Y</div>
<span>5,1000</span>
</div>
<!-- <div class="point">
<div class="pointItem" @click="drawPointStep4('Y', '#FB54A1')">
绘制平均消费金额Y
</div>
<span>1000</span>
</div> -->
</div>
</div>
</div>
</div>
<div class="line"></div>
<div class="caseBack">
<div class="title">
<img src="@/assets/images/步骤.png" alt="" />
<span>第五步划分客户类型</span>
</div>
<span style="line-height: 25px; font-size: 14px">
2 years ago
按照客户标准划分ABCD各属于哪类客户
<br />
1消费次数超过平均值每次消费力度也超过平均水平的客户判定为明星客户
<br />
2消费次数超过平均值但每次消费力度未达到平均水平的客户被判定为现金流客户
<br />
3消费未达到平均值但每次消费力度超过平均水平的客户是问题客户
<br />
4消费未达到平均值消费力度也未达到平均水平的客户属于瘦狗客户
</span>
<div style="margin-top: 10px; display: flex">
<div id="charts3" style="width: 500px; height: 400px"></div>
<div>
<div class="submit" @click="step5Submit"></div>
<div class="drawPoint">
<div class="point">
2 years ago
<div class="pointItem" @click="drawQuadrant('明星客户', 'rgba(52, 134, 207, 0.8)')">明星客户</div>
</div>
<div class="point">
2 years ago
<div class="pointItem" @click="drawQuadrant('现金流客户', 'rgba(0, 184, 105, 0.8)')">现金流客户</div>
</div>
<div class="point">
2 years ago
<div class="pointItem" @click="drawQuadrant('问题客户', 'rgba(177, 130, 192, 0.8)')">问题客户</div>
</div>
<div class="point">
2 years ago
<div class="pointItem" @click="drawQuadrant('瘦狗客户', 'rgba(254, 141, 42, 0.8)')">瘦狗客户</div>
</div>
</div>
</div>
</div>
</div>
<div class="line"></div>
<div class="caseBack">
<div class="title">
<img src="@/assets/images/步骤.png" alt="" />
<span>第六步针对不同的客户类型制定不同的营销策略</span>
</div>
2 years ago
<span style="line-height: 25px; font-size: 14px">当波士顿矩阵应用于客户画像时候可以大致分析出不同用户的客户画像</span>
<div class="customerType" style="width: 887px">
<img src="@/assets/images/客户1.png" alt="" />
<span>明星客户这类客户需要重点关注并给予最高的礼遇</span>
</div>
<div class="customerType" style="width: 887px">
<img src="@/assets/images/客户2.png" alt="" />
2 years ago
<span>现金流客户这类客户通常消费频次比较频繁能给企业带来较为稳定的现金流这类客户是企业利润基石</span>
</div>
<div class="customerType" style="width: 887px">
<img src="@/assets/images/客户3.png" alt="" />
2 years ago
<span>问题客户这类客户最有希望转化为明星客户但是因为客户存在一定的潜在问题导致消费频次不高这类客户需要利用客服进行重点跟进和长期跟踪</span>
</div>
<div class="customerType" style="width: 887px">
<img src="@/assets/images/客户1.png" alt="" />
2 years ago
<span>瘦狗客户这类客户通常占企业客户的大多数只需要一般性维护不需要投入重点维系</span>
</div>
</div>
</div>
2 years ago
<pop-modal :showModel="dialogVisible" @closePop="dialogVisible = false">
<template v-slot:content>
<p style="line-height: 25px; font-size: 14px">
2 years ago
波士顿矩阵BCG Matrix又称市场增长率-相对市场份额矩阵由美国著名的管理学家波士顿咨询公司创始人布鲁斯·亨德森于1970年首创它是通过销售增长率反应市场引力的指标和市场占有率反应企业实力的指标来分析决定企业的产品结构
<br />
市场吸引力包括企业销售量增长率目标市场容量竞争对手强弱利润高低等其中最重要的是反映市场引力的综合指标销售增长率这是决定企业产品结构是否合理的外在因素
<br />
2 years ago
企业实力包括市场占有率技术设备资金利用能力等其中市场占有率是决定企业产品结构的内在因素他直接显示出企业的竞争实力
</p>
2 years ago
<img src="@/assets/images/u3678.png" alt="" />
<br />
2 years ago
<span style="line-height: 25px; font-size: 14px">
2 years ago
波士顿矩阵将产品类型分为四种
<br />
1明星类产品高增长且高市占发展前景好竞争力强需加大投资以支持其发展
<br />
2问题类产品高增长但低市占发展前景好但市场开拓不足需谨慎投资
<br />
3现金牛产品低增长但高市占成熟市场的领导者应降低投资维持市占并延缓衰退
<br />
4瘦狗类产品低增长且低市占理论率低甚至亏损应采取撤退战略
</span>
<br />
<br />
2 years ago
<span style="line-height: 25px; font-size: 14px">
2 years ago
当波士顿矩阵应用于客户画像时候可以大致分析出不同用户的客户画像
<br />
1消费次数超过平均值每次消费力度也超过平均水平的客户判定为明星客户这类客户需要重点关注并给予最高的礼遇
<br />
2消费次数超过平均值但每次消费力度未达到平均水平的客户被判定为现金流客户这类客户通常消费频次比较频繁能给企业带来较为稳定的现金流这类客户是企业利润基石
<br />
3消费未达到平均值但每次消费力度超过平均水平的客户是问题客户这类客户最有希望转化为明星客户但是因为客户存在一定的潜在问题导致消费频次不高这类客户需要利用客服进行重点跟进和长期跟踪
<br />
4消费未达到平均值消费力度也未达到平均水平的客户属于瘦狗客户这类客户通常占企业客户的大多数只需要一般性维护不需要投入重点维系
<br />
</span>
<br />
2 years ago
<img src="@/assets/images/u3682.png" alt="" />
</template>
</pop-modal>
</div>
</template>
<script setup>
2 years ago
import popModal from "@/views/components/popModal.vue";
import { getUserInfo } from "@/utils/auth";
import * as echarts from "echarts";
import { Chart } from "@antv/g2";
2 years ago
import * as portraitModel from "@/api/portraitModel";
import { downBlobFile } from "@/utils/index.js";
import { onMounted } from "vue";
const { proxy } = getCurrentInstance();
2 years ago
const baseUrl = import.meta.env.VITE_APP_BASE_API;
2 years ago
const dialogVisible = ref(false);
const knowledgeFlag = ref(false);
const chart1OptionData = ref([]);
const chart2OptionData = ref([]);
const chart3OptionData = ref([]);
const quadrant1 = ref("");
const quadrant2 = ref("");
const quadrant3 = ref("");
const quadrant4 = ref("");
const quadrant1Color = ref('')
const quadrant2Color = ref('')
const quadrant3Color = ref('')
const quadrant4Color = ref('')
const step1Data = ref([
{
name: "A",
amount: "2300",
},
{
name: "B",
amount: "2300",
},
{
name: "C",
amount: "2300",
},
{
name: "D",
amount: "2300",
},
]);
const fileTable1 = ref([
{
id: "A",
amount: "200",
time: "2023.02.01",
},
{
id: "B",
amount: "300",
time: "2023.02.02",
},
{
id: "A",
time: "2023.02.03",
amount: "200",
},
{
id: "D",
time: "2023.02.04",
amount: "150",
},
{
id: "C",
time: "2023.02.05",
amount: "100",
},
{
id: "B",
time: "2023.02.06",
amount: "400",
},
{
id: "C",
time: "2023.02.07",
amount: "50",
},
{
id: "D",
time: "2023.02.08",
amount: "250",
},
{
id: "D",
time: "2023.02.09",
amount: "200",
},
{
id: "B",
time: "2023.02.10",
amount: "300",
},
{
id: "D",
time: "2023.02.11",
amount: "200",
},
{
id: "C",
time: "2023.02.12",
amount: "50",
},
{
id: "D",
time: "2023.02.13",
amount: "100",
},
{
id: "A",
time: "2023.02.14",
amount: "400",
},
{
id: "C",
time: "2023.02.15",
amount: "200",
},
{
id: "B",
time: "2023.02.16",
amount: "200",
},
{
id: "C",
time: "2023.02.17",
amount: "150",
},
{
id: "D",
time: "2023.02.18",
amount: "300",
},
{
id: "C",
time: "2023.02.19",
amount: "50",
},
{
id: "D",
time: "2023.02.20",
amount: "200",
},
]);
const step2Data = ref([
{
name: "A",
amount: "3",
account: "800",
},
{ name: "B", amount: "4", account: "1200" },
{ name: "C", amount: "6", account: "600" },
{ name: "D", amount: "7", account: "1400" },
{ name: "平均值", amount: "7", account: "1400" },
]);
const step3Data = ref([
{
data1: "男士配饰",
data2: "5900",
},
{
data1: "床上用品",
data2: "2400",
},
{
data1: "婴儿用品",
data2: "1100",
},
{
data1: "儿童服装",
data2: "600",
},
]);
const step4Data = ref([
{
data1: "男士配饰",
data2: "5900",
data3: "59%",
data4: "2",
},
{
data1: "床上用品",
data2: "2400",
data3: "83%",
data4: "3",
},
{
data1: "婴儿用品",
data2: "1100",
data3: "94%",
data4: "1",
},
{
data1: "儿童服装",
data2: "600",
data3: "100%",
data4: "1",
},
]);
const step5Data = ref([
{
title: "平均值",
},
]);
const step6Data = ref([
{
data1: "1",
data2: "小明",
data3: "4",
data4: "2",
data5: "4",
},
{
data1: "2",
data2: "小红",
data3: "5",
data4: "2",
data5: "2",
},
{
data1: "3",
data2: "小李",
data3: "5",
data4: "1",
data5: "1",
},
]);
const rulesTable = ref([
{
data1: "1.重要价值用户",
data2: "高",
data3: "高",
data4: "高",
},
{
data1: "2.重要发展用户",
data2: "高",
data3: "低",
data4: "高",
},
{
data1: "3.重要保持用户",
data2: "低",
data3: "高",
data4: "高",
},
{
data1: "4.重要挽留用户",
data2: "低",
data3: "低",
data4: "高",
},
{
data1: "5.一般价值用户",
data2: "高",
data3: "高",
data4: "低",
},
{
data1: "6.一般发展用户",
data2: "高",
data3: "低",
data4: "低",
},
{
data1: "7.一般保持用户",
data2: "低",
data3: "高",
data4: "低",
},
{
data1: "6.一般挽留用户",
data2: "低",
data3: "低",
data4: "低",
},
]);
const typeData = ref([
{
data1: "A类商品",
data2: "占总销售额的80%,需要重点关注",
},
{
data1: "B类商品",
data2: "占总销售额的10%,给予次要关注",
},
{
data1: "C类商品",
data2: "占总销售额的10%,给予一般关注",
},
]);
//第三步定义数据
const option = ref({});
const drawPointName = ref("");
const drawPointColor = ref("");
const pointInGrid = ref([]);
//第四步定义数据
const option2 = ref({});
const drawPointNameStep4 = ref("");
const drawPointColorStep4 = ref("");
const pointInGridStep4 = ref([]);
//第五步定义数据
const optionStep5 = ref({});
const drawPointNameStep5 = ref("");
const drawPointColorStep5 = ref("");
const pointInGridStep5 = ref([]);
const errorNum = ref(0);
const step1Error = ref(0);
const step2Error = ref(0);
const step3Error = ref(0);
const step4Error = ref(0);
const step5Error = ref(0);
const step1AnswerFlag = ref(false);
const step2AnswerFlag = ref(false);
const step3AnswerFlag = ref(false);
const step4AnswerFlag = ref(false);
const step5AnswerFlag = ref(false);
onMounted(() => {
2 years ago
getData();
// step3EchartInit();
// step4EchartInit();
// step5EchartInit();
2 years ago
});
onBeforeUnmount(() => {
saveData();
});
const drawPoint = (point, color) => {
// console.log(point);
// let Apoint = point
// if(Apoint == drawPointName.value){
// proxy.$modal.msgError("请勿绘制重复的点");
// return;
// }
drawPointName.value = point;
drawPointColor.value = color;
// option.value.series[0].data.push(pointInGrid);
// option.value && myChart.setOption(option.value);
};
const drawPointStep4 = (point, color) => {
drawPointNameStep4.value = point;
drawPointColorStep4.value = color;
};
const step3EchartInit = () => {
var chartDom = document.getElementById("charts1");
var myChart = echarts.init(chartDom, "dark");
// var option;
option.value = {
xAxis: {
name: "X",
show: true,
max: 10,
min: 0,
interval: 1,
axisPointer: {
show: true,
label: {
precision: 0,
},
// snap: true,
},
},
yAxis: {
name: "Y",
show: true,
interval: 200,
max: 2000,
min: 0,
axisPointer: {
show: true,
// snap: true,
label: {
precision: 0,
},
},
},
series: [
{
symbolSize: 20,
label: {
show: true, // 显示标签
formatter: function (params) {
// 自定义显示的文本内容params是包含数据信息的对象
return params.data.name;
},
position: "top", // 文本位置,可以是 'top', 'left', 'right', 'bottom', 'inside', 或者是 {top, left} 形式的具体位置
},
itemStyle: {
color: function (params) {
// 自定义显示的文本内容params是包含数据信息的对象
return params.data.color;
},
borderColor: "#fff",
},
// data: [
// // { value: [3, 800], name: "A" },
// // { value: [4, 1200], name: "B" },
// // { value: [6, 600], name: "C" },
// // { value: [7, 1400], name: "D" },
// // { value: [10, 1400], },
// // [4, 1200],
// // [6, 600],
// // [7, 1400],
// ],
data: chart1OptionData.value,
type: "scatter",
},
],
};
option.value && myChart.setOption(option.value);
myChart.getZr().on("click", function (param) {
if (drawPointName.value == "") {
proxy.$modal.msgError("请选择要绘制的点");
return;
}
//有重复的点就重新绘制
for (let i in chart1OptionData.value) {
if (chart1OptionData.value[i].name == drawPointName.value) {
chart1OptionData.value.splice(i, 1);
}
}
const pointInPixel = [param.offsetX, param.offsetY];
console.log("pointInPixel", pointInPixel);
// 使用 convertFromPixel方法 转换像素坐标值到逻辑坐标系上的点。获取点击位置对应的x轴数据的索引 值,借助于索引值的获取到其它的信息
// 转换X轴坐标
// let pointInGrid = myChart.convertFromPixel(
// { seriesIndex: 0 },
// pointInPixel
// );
2 years ago
pointInGrid.value = myChart.convertFromPixel({ seriesIndex: 0 }, pointInPixel);
// 转换Y轴坐标
// let pointInGrid2 = myChart.convertFromPixel({ seriesIndex: 1 }, pointInPixel);
// x轴数据的索引值
console.log("pointInGrid", pointInGrid.value);
// option.value.series[0].data.push({
// value: pointInGrid.value,
// name: drawPointName.value,
// color: drawPointColor.value,
// });
chart1OptionData.value.push({
value: pointInGrid.value,
name: drawPointName.value,
color: drawPointColor.value,
});
option.value && myChart.setOption(option.value);
// console.log();
// 所点击点的X轴坐标点所在X轴data的下标
// let xIndex = pointInGrid[0];
// // 所点击点的Y轴坐标点数值
// let yIndex = pointInGrid2[1];
// // 使用getOption() 获取图表的option
// let op = myChart.getOption();
// //获取到x轴的索引值和option之后我们就可以获取我们需要的任意数据。
// // 点击点的X轴对应坐标的名称
// var time = op.xAxis[0].data[xIndex];
// // 点击点的series -- data对应的值
// var value = op.series[0].data[xIndex];
// console.log("val", time);
});
};
const step4EchartInit = () => {
var chartDom = document.getElementById("charts2");
var myChart = echarts.init(chartDom, "dark");
// var option;
option2.value = {
xAxis: {
name: "X",
show: true,
max: 10,
min: 0,
interval: 1,
axisPointer: {
show: true,
label: {
precision: 0,
},
// snap: true,
},
},
yAxis: {
name: "Y",
show: true,
interval: 200,
max: 2000,
min: 0,
axisPointer: {
show: true,
// snap: true,
label: {
precision: 0,
},
},
},
series: [
{
symbolSize: 20,
label: {
show: true, // 显示标签
formatter: function (params) {
// 自定义显示的文本内容params是包含数据信息的对象
return params.data.name;
},
position: "top", // 文本位置,可以是 'top', 'left', 'right', 'bottom', 'inside', 或者是 {top, left} 形式的具体位置
},
itemStyle: {
color: function (params) {
// 自定义显示的文本内容params是包含数据信息的对象
return params.data.color;
},
borderColor: "#fff",
},
// data: [
// // { value: [3, 800], name: "A" },
// // { value: [4, 1200], name: "B" },
// // { value: [6, 600], name: "C" },
// // { value: [7, 1400], name: "D" },
// // { value: [10, 1400], },
// // [4, 1200],
// // [6, 600],
// // [7, 1400],
// ],
data: chart2OptionData.value,
type: "scatter",
},
],
};
option2.value && myChart.setOption(option2.value);
myChart.getZr().on("click", function (param) {
if (drawPointNameStep4.value == "") {
proxy.$modal.msgError("请选择要绘制的点");
return;
}
//有重复的点就重新绘制
for (let i in chart2OptionData.value) {
if (chart2OptionData.value[i].name == drawPointNameStep4.value) {
chart2OptionData.value.splice(i, 1);
}
}
const pointInPixel = [param.offsetX, param.offsetY];
console.log("pointInPixel4", pointInPixel);
//将偏移值转化为坐标值
2 years ago
pointInGridStep4.value = myChart.convertFromPixel({ seriesIndex: 0 }, pointInPixel);
console.log("pointInGrid4", pointInGridStep4.value);
// option2.value.series[0].data.push({
// value: pointInGridStep4.value,
// name: drawPointNameStep4.value,
// color: drawPointColorStep4.value,
// });
chart2OptionData.value.push({
value: pointInGridStep4.value,
name: drawPointNameStep4.value,
color: drawPointColorStep4.value,
});
option2.value && myChart.setOption(option2.value);
});
};
const step5EchartInit = () => {
// 散点数据
const marksData = [
{
name: "A",
value: [3, 800],
color: "#009FF1",
},
{
name: "B",
value: [4, 1200],
color: "#FB54A1",
},
{
name: "C",
value: [6, 600],
color: "#FE8D2A",
},
{
name: "D",
value: [7, 1400],
color: "#6E70F0",
},
];
// 中心线
const centerLine = [
{
name: "y",
xAxis: 5,
},
{
name: "x",
yAxis: 1000,
},
];
// 中心点
const centerMark = [
{
value: "中心点",
coord: [5, 1000],
},
];
optionStep5.value = {
tooltip: {
axisPointer: {
show: true,
type: "cross",
lineStyle: {
type: "dashed",
width: 1,
},
label: {
backgroundColor: "#555",
},
},
},
grid: {
left: 50,
right: 50,
bottom: "4%",
top: "6%",
containLabel: true,
},
xAxis: {
scale: true,
max: 10,
min: 0,
interval: 1,
axisLine: {
lineStyle: {
color: "#ddd",
},
},
axisLabel: {
color: "#666",
},
axisPointer: {
show: true,
label: {
precision: 0,
},
// snap: true,
},
splitLine: {
lineStyle: {
color: "#eee",
},
},
},
yAxis: {
max: 2000,
min: 0,
interval: 200,
scale: true,
axisLine: {
lineStyle: {
color: "#ddd",
},
},
axisPointer: {
show: true,
label: {
precision: 0,
},
// snap: true,
},
axisLabel: {
color: "#666",
},
splitLine: {
lineStyle: {
color: "#eee",
},
},
},
series: [
{
type: "scatter",
data: marksData,
label: {
show: true,
position: "bottom",
formatter: "{b}",
},
itemStyle: {
shadowBlur: 2,
shadowColor: "rgba(120, 36, 50, 0.5)",
shadowOffsetY: 1,
color: function (params) {
// 自定义显示的文本内容params是包含数据信息的对象
return params.data.color;
},
// color: function (e) {
// let randomColor =
// "rgba(" +
// Math.floor(Math.random() * 240) +
// "," +
// Math.floor(Math.random() * 240) +
// "," +
// Math.floor(Math.random() * 240) +
// "," +
// ".8" +
// ")";
// return randomColor.substring();
// },
},
// 各象限区域需要结合中心线的位置来画出四个象限的markArea
markArea: {
silent: true,
data: [
// 第一象限
[
{
// 标域左上角的数据,也就是要设置矩形左边和上边的值
name: "第一象限",
xAxis: 5, // x 轴开始位置(中心线的值)
yAxis: 2000, // y 轴结束位置(y轴最大值)
itemStyle: {
// color: "rgba(52, 134, 207, 0.6)",
},
label: {
position: "inside",
color: "#fff",
fontSize: 22,
},
},
{
// 标域右下角的数据,矩形域右边和下边的值
yAxis: 1000, // y 轴开始位置(中心线的值)
},
],
// 第二象限
[
{
name: "第二象限",
yAxis: 2000, // y 轴结束位置(取y轴最大值)
itemStyle: {
// color: "rgba(177, 130, 192, 0.6)",
},
label: {
position: "inside",
color: "#fff",
fontSize: 22,
},
},
{
xAxis: 5, // x 轴结束位置(中心线位置)
yAxis: 1000, // y 轴开始位置(中心线位置)
},
],
// 第三象限
[
{
name: "第三象限",
yAxis: 1000, // y 轴结束位置(中心线位置)
itemStyle: {
// color: "rgba(254, 141, 42, 0.6)",
},
label: {
position: "inside",
color: "#fff",
fontSize: 22,
},
},
{
xAxis: 5, // x 轴结束位置(中心线位置)
yAxis: 0, // y 轴开始位置(y轴最小值
},
],
// 第四象限
[
{
name: "第四象限",
xAxis: 5, // x 轴开始位置(中心线位置)
yAxis: 1000, // y 轴结束位置(中心线位置)
itemStyle: {
// color: "rgba(0, 184, 105, 0.6)",
},
label: {
position: "inside",
color: "#FFF",
fontSize: 22,
},
},
{
yAxis: 0, // y轴开始位置(y轴最小值
},
],
],
},
// 中心点交集象限轴
markLine: {
silent: true, // 是否不响应鼠标事件
precision: 2, // 精度
lineStyle: {
type: "solid",
color: "#00aca6",
},
label: {
color: "#00aca6",
position: "end",
formatter: "{b}",
},
data: centerLine,
},
// 中心点
markPoint: {
symbol: "roundRect",
symbolSize: 15,
itemStyle: {
color: "rgba(234, 85, 6, .8)",
},
label: {
position: "top",
},
data: centerMark,
},
},
],
};
optionStep5.value.series[0].markArea.data[0][0].name = quadrant1.value;
optionStep5.value.series[0].markArea.data[1][0].name = quadrant2.value
optionStep5.value.series[0].markArea.data[2][0].name = quadrant3.value
optionStep5.value.series[0].markArea.data[3][0].name = quadrant4.value
optionStep5.value.series[0].markArea.data[0][0].itemStyle.color = quadrant1Color.value;
optionStep5.value.series[0].markArea.data[1][0].itemStyle.color = quadrant2Color.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;
var chartDom = document.getElementById("charts3");
var myChart = echarts.init(chartDom, "dark");
optionStep5.value && myChart.setOption(optionStep5.value);
myChart.getZr().on("click", function (param) {
if (drawPointColorStep5.value == "") {
proxy.$modal.msgError("请选择要绘制的点");
return;
}
const pointInPixel = [param.offsetX, param.offsetY];
console.log("pointInPixel5", pointInPixel);
//将偏移值转化为坐标值
2 years ago
pointInGridStep5.value = myChart.convertFromPixel({ seriesIndex: 0 }, pointInPixel);
console.log("pointInGrid5", pointInGridStep5.value);
if (pointInGridStep5.value[0] > 5 && pointInGridStep5.value[1] > 1000) {
2 years ago
optionStep5.value.series[0].markArea.data[0][0].itemStyle.color = drawPointColorStep5.value;
optionStep5.value.series[0].markArea.data[0][0].name = drawPointNameStep5.value;
console.log(optionStep5.value);
}
if (pointInGridStep5.value[0] < 5 && pointInGridStep5.value[1] > 1000) {
2 years ago
optionStep5.value.series[0].markArea.data[1][0].itemStyle.color = drawPointColorStep5.value;
optionStep5.value.series[0].markArea.data[1][0].name = drawPointNameStep5.value;
console.log(optionStep5.value);
}
if (pointInGridStep5.value[0] < 5 && pointInGridStep5.value[1] < 1000) {
2 years ago
optionStep5.value.series[0].markArea.data[2][0].itemStyle.color = drawPointColorStep5.value;
optionStep5.value.series[0].markArea.data[2][0].name = drawPointNameStep5.value;
console.log(optionStep5.value);
}
if (pointInGridStep5.value[0] > 5 && pointInGridStep5.value[1] < 1000) {
2 years ago
optionStep5.value.series[0].markArea.data[3][0].itemStyle.color = drawPointColorStep5.value;
optionStep5.value.series[0].markArea.data[3][0].name = drawPointNameStep5.value;
console.log(optionStep5.value);
}
optionStep5.value && myChart.setOption(optionStep5.value);
});
};
const drawQuadrant = (name, color) => {
drawPointColorStep5.value = color;
drawPointNameStep5.value = name;
console.log(drawPointColorStep5.value);
};
const step1Submit = () => {
step1Error.value = 0;
for (let i in step1Data.value) {
if (!step1Data.value[i].params1 || !step1Data.value[i].params2) {
proxy.$modal.msgError("请先完成所有填空");
return;
}
}
if (step1Data.value[0].params1 && step1Data.value[0].params1 !== "3") {
step1Error.value++;
}
if (step1Data.value[0].params2 && step1Data.value[0].params2 !== "800") {
step1Error.value++;
}
if (step1Data.value[1].params1 && step1Data.value[1].params1 !== "4") {
step1Error.value++;
}
if (step1Data.value[1].params2 && step1Data.value[1].params2 !== "1200") {
step1Error.value++;
}
if (step1Data.value[2].params1 && step1Data.value[2].params1 !== "6") {
step1Error.value++;
}
if (step1Data.value[2].params2 && step1Data.value[2].params2 !== "600") {
step1Error.value++;
}
if (step1Data.value[3].params1 && step1Data.value[3].params1 !== "7") {
step1Error.value++;
}
if (step1Data.value[3].params2 && step1Data.value[3].params2 !== "1400") {
step1Error.value++;
}
console.log(step1Error.value, "错误数");
proxy.$modal.msgSuccess("提交成功");
step1AnswerFlag.value = true;
2 years ago
for (let k in step1Data.value) {
step2Data.value[k].amount = step1Data.value[k].params1;
step2Data.value[k].account = step1Data.value[k].params2;
}
};
const step2Submit = () => {
step2Error.value = 0;
if (!step2Data.value[4].params1 || !step2Data.value[4].params2) {
proxy.$modal.msgError("请先完成所有填空");
return;
}
if (step2Data.value[4].params1 && step2Data.value[4].params1 !== "5") {
step2Error.value++;
}
if (step2Data.value[4].params2 && step2Data.value[4].params2 !== "1000") {
step2Error.value++;
}
console.log(step2Error.value, "错误数");
proxy.$modal.msgSuccess("提交成功");
step2AnswerFlag.value = true;
};
const step3Submit = () => {
step3Error.value = 0;
for (let i in chart1OptionData.value) {
// console.log(option.value.series[0].data[i]);
if (chart1OptionData.value[i].name == "A") {
if (Math.round(chart1OptionData.value[i].value[0]) != 3 || Math.round(chart1OptionData.value[i].value[1]) != 800) {
step3Error.value++;
}
}
if (chart1OptionData.value[i].name == "B") {
if (Math.round(chart1OptionData.value[i].value[0]) != 4 || Math.round(chart1OptionData.value[i].value[1]) != 1200) {
step3Error.value++;
}
}
if (chart1OptionData.value[i].name == "C") {
if (Math.round(chart1OptionData.value[i].value[0]) != 6 || Math.round(chart1OptionData.value[i].value[1]) != 600) {
step3Error.value++;
}
}
if (chart1OptionData.value[i].name == "D") {
if (Math.round(chart1OptionData.value[i].value[0]) != 7 || Math.round(chart1OptionData.value[i].value[1]) != 1400) {
step3Error.value++;
}
}
}
console.log(step3Error.value, "错误数");
proxy.$modal.msgSuccess("提交成功");
step3AnswerFlag.value = true;
// chart2OptionData.value = chart1OptionData.value;
// step4EchartInit();
};
const step4Submit = () => {
step4Error.value = 0;
for (let i in chart2OptionData.value) {
// console.log(option2.value.series[0].data[i]);
if (chart2OptionData.value[i].name == "E") {
if (Math.round(chart2OptionData.value[i].value[0]) != 5 || Math.round(chart2OptionData.value[i].value[1]) != 1000) {
console.log(chart2OptionData.value[i]);
step4Error.value++;
}
}
}
console.log(step4Error.value, "错误数");
proxy.$modal.msgSuccess("提交成功");
step4AnswerFlag.value = true;
};
const step5Submit = () => {
step5Error.value = 0;
if (optionStep5.value.series[0].markArea.data[0][0].name != "明星客户") {
step5Error.value++;
}
if (optionStep5.value.series[0].markArea.data[1][0].name != "问题客户") {
step5Error.value++;
}
if (optionStep5.value.series[0].markArea.data[2][0].name != "瘦狗客户") {
step5Error.value++;
}
if (optionStep5.value.series[0].markArea.data[3][0].name != "现金流客户") {
step5Error.value++;
}
console.log(step5Error.value, "错误数");
proxy.$modal.msgSuccess("提交成功");
step5AnswerFlag.value = true;
};
2 years ago
const downloadData = () => {
// console.log(666);
2 years ago
// portraitModel
// .downloadDataByBoston({})
// .then((res) => {
// // console.log(res,'--');
// const blob = new Blob([res], { type: "application/vnd.ms-excel" });
// downBlobFile(`案例数据-波士顿矩阵分析`, blob);
// })
// .catch((error) => {});
window.open(baseUrl + "/api/downDataByUserPortrait/bostonMatrixAnalysisData");
};
const submitData = () => {
2 years ago
if (!step1AnswerFlag.value || !step2AnswerFlag.value || !step3AnswerFlag.value || !step4AnswerFlag.value || !step5AnswerFlag.value) {
proxy.$modal.msgError("请先完成所有步骤!");
return;
}
2 years ago
errorNum.value = step1Error.value + step2Error.value + step3Error.value + step4Error.value + step5Error.value;
console.log(errorNum.value, "总错误次数");
portraitModel
.submit({
userId: JSON.parse(getUserInfo()).userId,
taskName: "波士顿矩阵分析",
numberOfErrors: errorNum.value,
})
.then((res) => {
proxy.$modal.msgSuccess("提交成功");
})
.catch((error) => {});
};
2 years ago
const saveData = () => {
const params = {
stepFiveA: step1Data.value[0].params1,
stepFiveB: step1Data.value[0].params2,
stepFiveC: step1Data.value[1].params1,
stepFiveD: step1Data.value[1].params2,
stepSixA: step1Data.value[2].params1,
stepSixB: step1Data.value[2].params2,
stepSixC: step1Data.value[3].params1,
stepSixD: step1Data.value[3].params2,
stepSevenA: step2Data.value[4].params1,
stepSevenB: step2Data.value[4].params2,
stepSevenC: JSON.stringify(chart1OptionData.value),
stepSevenD: JSON.stringify(chart2OptionData.value),
stepEightA: optionStep5.value.series[0].markArea.data[0][0].name,
stepEightB: optionStep5.value.series[0].markArea.data[1][0].name,
stepEightC: optionStep5.value.series[0].markArea.data[2][0].name,
stepEightD: optionStep5.value.series[0].markArea.data[3][0].name,
stepNineA: optionStep5.value.series[0].markArea.data[0][0].itemStyle.color,
stepNineB: optionStep5.value.series[0].markArea.data[1][0].itemStyle.color,
stepNineC: optionStep5.value.series[0].markArea.data[2][0].itemStyle.color,
stepNineD: optionStep5.value.series[0].markArea.data[3][0].itemStyle.color,
2 years ago
// stepTenA: step2Data.value[14].params,
// stepTenB: step2Data.value[15].params,
// stepTenC: step2Data.value[16].params,
// stepTenD: step2Data.value[17].params,
// stepElevenA: step2Data.value[18].params,
// stepOneA: step2Data.value[19].params,
// stepOneB: step2Data.value[20].params,
// stepOneC: step2Data.value[21].params,
// stepOneD: step2Data.value[22].params,
// stepTwoA: step2Data.value[23].params,
// stepTwoB: step2Data.value[24].params,
// stepTwoC: step2Data.value[25].params,
// stepThreeA: step2Data.value[26].params,
// stepThreeB: step2Data.value[27].params,
// stepThreeC: step2Data.value[28].params,
// stepThreeD: step2Data.value[29].params,
// stepFourA: step2Data.value[30].params,
// stepFourB: step2Data.value[31].params,
// stepFourC: step2Data.value[32].params,
// stepFourD: step2Data.value[33].params,
// stepNewOne: step2Data.value[34].params,
// stepNewTwo: step2Data.value[35].params,
// stepNewThree: step2Data.value[36].params,
// stepNewFive: step5DataTable3.value[3].params2,
// stepNewSix: step5DataTable3.value[4].params1,
// stepNewEight: step5DataTable3.value[4].params2,
};
portraitModel
.saveData({
userId: JSON.parse(getUserInfo()).userId,
module: "波士顿矩阵分析",
...params,
})
.then((res) => {})
.catch((error) => {});
};
const getData = () => {
portraitModel
.getData({
userId: JSON.parse(getUserInfo()).userId,
module: "波士顿矩阵分析",
})
.then((res) => {
step1Data.value[0].params1 = res.data.stepFiveA;
step1Data.value[0].params2 = res.data.stepFiveB;
step1Data.value[1].params1 = res.data.stepFiveC;
step1Data.value[1].params2 = res.data.stepFiveD;
step1Data.value[2].params1 = res.data.stepSixA;
step1Data.value[2].params2 = res.data.stepSixB;
step1Data.value[3].params1 = res.data.stepSixC;
step1Data.value[3].params2 = res.data.stepSixD;
step2Data.value[4].params1 = res.data.stepSevenA;
step2Data.value[4].params2 = res.data.stepSevenB;
chart1OptionData.value = JSON.parse(res.data.stepSevenC);
// console.log(JSON.parse(res.data.stepSevenC),'666');
chart2OptionData.value = JSON.parse(res.data.stepSevenD);
quadrant1.value = res.data.stepEightA;
quadrant2.value = res.data.stepEightB;
quadrant3.value = res.data.stepEightC;
quadrant4.value = res.data.stepEightD;
quadrant1Color.value = res.data.stepNineA;
quadrant2Color.value = res.data.stepNineB;
quadrant3Color.value = res.data.stepNineC;
quadrant4Color.value = res.data.stepNineD;
2 years ago
// step2Data.value[14].params = res.data.stepTenA;
// step2Data.value[15].params = res.data.stepTenB;
// step2Data.value[16].params = res.data.stepTenC;
// step2Data.value[17].params = res.data.stepTenD;
// step2Data.value[18].params = res.data.stepElevenA;
// step2Data.value[19].params = res.data.stepOneA;
// step2Data.value[20].params = res.data.stepOneB;
// step2Data.value[21].params = res.data.stepOneC;
// step2Data.value[22].params = res.data.stepOneD;
// step2Data.value[23].params = res.data.stepTwoA;
// step2Data.value[24].params = res.data.stepTwoB;
// step2Data.value[25].params = res.data.stepTwoC;
// step2Data.value[26].params = res.data.stepThreeA;
// step2Data.value[27].params = res.data.stepThreeB;
// step2Data.value[28].params = res.data.stepThreeC;
// step2Data.value[29].params = res.data.stepThreeD;
// step2Data.value[30].params = res.data.stepFourA;
// step2Data.value[31].params = res.data.stepFourB;
// step2Data.value[32].params = res.data.stepFourC;
// step2Data.value[33].params = res.data.stepFourD;
// step2Data.value[34].params = res.data.stepNewOne;
// step2Data.value[35].params = res.data.stepNewTwo;
// step2Data.value[36].params = res.data.stepNewThree;
// step5DataTable3.value[3].params2 = res.data.stepNewFive;
// step5DataTable3.value[4].params1 = res.data.stepNewSix;
// step5DataTable3.value[4].params2 = res.data.stepNewEight;
2 years ago
// console.log(JSON.parse(res.data.stepSevenC));
step3EchartInit();
step4EchartInit();
step5EchartInit();
2 years ago
})
.catch((error) => {});
};
const retrain = () => {
// console.log(666);
portraitModel
.retrain({
userId: JSON.parse(getUserInfo()).userId,
module: "波士顿矩阵分析",
})
.then((res) => {
proxy.$modal.msgSuccess("重新实训成功");
for (let i in step1Data.value) {
step1Data.value[i].params1 = "";
step1Data.value[i].params2 = "";
}
step2Data.value[4].params1 = "";
step2Data.value[4].params2 = "";
})
.catch((error) => {});
};
defineExpose({
submitData,
2 years ago
retrain,
// practicalTraining,
});
</script>
<style scoped lang="scss">
.content {
width: 100%;
background: rgba(0, 29, 64, 0.5);
border: 1px solid #0452c6;
padding: 10px;
// opacity: 0.5;
.import {
display: flex;
font-size: 15px;
font-weight: bold;
width: 180px;
height: 56px;
background-image: url("@/assets/images/taskImport.png");
background-size: 180px 56px;
text-align: center;
align-items: center;
line-height: 56px;
cursor: pointer;
img {
margin-left: 20px;
margin-right: 15px;
}
}
.caseBack {
.title {
font-weight: bold;
margin-top: 10px;
display: flex;
align-items: center;
span {
margin-left: 10px;
}
}
.download {
cursor: pointer;
margin-left: 20px;
color: #000;
padding-left: 10px;
font-size: 14px;
text-align: center;
line-height: 31px;
width: 89px;
height: 31px;
background: url("@/assets/images/downloadIcon.png");
}
.submit {
cursor: pointer;
margin-left: 20px;
color: #000;
padding-left: 10px;
font-size: 14px;
text-align: center;
line-height: 31px;
width: 99px;
height: 31px;
background: url("@/assets/images/提交任务.png");
}
.customerType {
padding-left: 10px;
display: flex;
align-items: center;
width: 945px;
height: 26px;
background: #003b75;
border-radius: 10px;
border: 1px solid #0052a3;
font-size: 12px;
margin-top: 10px;
img {
margin-right: 10px;
}
}
.drawPoint {
margin-left: 20px;
.point {
display: flex;
align-items: center;
margin-top: 15px;
.pointItem {
// width: 73px;
height: 19px;
padding-left: 10px;
padding-right: 10px;
background: #002651;
border: 1px solid #67b3d6;
text-align: center;
line-height: 19px;
font-size: 12px;
cursor: pointer;
}
span {
font-size: 12px;
color: #6e70f0;
margin-left: 10px;
}
}
}
}
.line {
width: 1400px;
height: 1px;
border: 1px solid #0452c6;
opacity: 0.5;
margin-top: 20px;
margin-bottom: 20px;
}
}
::v-deep .el-table tr {
background-color: #002652 !important;
color: #fff;
}
2 years ago
::v-deep .el-table td {
padding-top: 4px;
padding-bottom: 4px;
}
</style>