|
|
|
|
|
<template>
|
|
|
|
|
|
<div class="differentiation app-container">
|
|
|
|
|
|
<div class="handren">
|
|
|
|
|
|
<div class="left">
|
|
|
|
|
|
<el-button>SPAN模型</el-button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="right">
|
|
|
|
|
|
<el-button @click="dialogVisible = true" type="primary" id="brtn">任务背景与目标</el-button>
|
|
|
|
|
|
<popModel :showModel="dialogVisible" title="任务背景:" @closePop="dialogVisible = false">
|
|
|
|
|
|
<template v-slot:content>
|
|
|
|
|
|
<p style="font-size: 1rem">
|
|
|
|
|
|
产品差异化定位的理论核心在于借助产品功能、性能或技术方面的独特性,精准满足消费者尚未被充分满足的需求。这种独特性可以是产品的某种特殊功能、卓越的性能、创新的技术,或者是独特的款式和设计等。
|
|
|
|
|
|
<br />
|
|
|
|
|
|
<br />
|
|
|
|
|
|
|
|
|
|
|
|
差异化定位的类型:
|
|
|
|
|
|
<br />
|
|
|
|
|
|
|
|
|
|
|
|
①基于功能属性的差异化定位:
|
|
|
|
|
|
<br />
|
|
|
|
|
|
|
|
|
|
|
|
强调产品在功能、性能或技术方面的独特性,以满足消费者的特定需求。
|
|
|
|
|
|
<br />
|
|
|
|
|
|
|
|
|
|
|
|
例如,游戏手机可能强调其出色的拍照性能和游戏性能,以吸引游戏爱好者。
|
|
|
|
|
|
<br />
|
|
|
|
|
|
|
|
|
|
|
|
②基于市场细分与品类创新的差异化定位:
|
|
|
|
|
|
<br />
|
|
|
|
|
|
|
|
|
|
|
|
通过开辟新品类或聚焦细分市场,实现品牌的独特价值。
|
|
|
|
|
|
<br />
|
|
|
|
|
|
|
|
|
|
|
|
例如,一些企业可能推出针对特定人群(如老年人、儿童)的定制化产品,以满足他们的特殊需求。
|
|
|
|
|
|
<br />
|
|
|
|
|
|
|
|
|
|
|
|
③基于品牌文化的差异化定位:
|
|
|
|
|
|
<br />
|
|
|
|
|
|
|
|
|
|
|
|
通过塑造独特的品牌文化,使品牌在众多竞争对手中脱颖而出。
|
|
|
|
|
|
<br />
|
|
|
|
|
|
|
|
|
|
|
|
例如,一些咖啡品牌可能强调其手工感、历史传承或独特的制作工艺,以吸引追求品质生活和文化认同的消费者。
|
|
|
|
|
|
<br />
|
|
|
|
|
|
|
|
|
|
|
|
④基于情感化语言和视觉的差异化定位:
|
|
|
|
|
|
<br />
|
|
|
|
|
|
|
|
|
|
|
|
运用情感化的语言和视觉元素,增强品牌的感染力和记忆点。
|
|
|
|
|
|
<br />
|
|
|
|
|
|
|
|
|
|
|
|
例如,通过设计独特的品牌标志、广告语和包装等,使品牌在消费者心中留下深刻的印象。
|
|
|
|
|
|
<br />
|
|
|
|
|
|
<br />
|
|
|
|
|
|
|
|
|
|
|
|
任务目标:
|
|
|
|
|
|
<br />
|
|
|
|
|
|
<br />
|
|
|
|
|
|
|
|
|
|
|
|
使用SPAN模型进行产品差异化定位。
|
|
|
|
|
|
<br />
|
|
|
|
|
|
<br />
|
|
|
|
|
|
|
|
|
|
|
|
①根据打分结果评估竞争地位和市场吸引力,绘制矩阵,分析结果,为产品规划提供决策依据。
|
|
|
|
|
|
<br />
|
|
|
|
|
|
</p>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</popModel>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="caseBacktitle">
|
|
|
|
|
|
<img src="@/assets/images/步骤.png" alt="" />
|
|
|
|
|
|
<span>一、知识学习</span>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<p>
|
|
|
|
|
|
SPAN分析模型,全称Strategy Positioning Analysis(战略定位分析),是一种用于评估细分市场吸引力和公司竞争地位的工具,是一种细分市场分类排序模型,它从市场吸引力和企业竞争力两个角度进行深入分析,通过量化分析的方法,帮助企业识别并优先选定有潜力的细分市场,为产品规划和市场进入策略提供决策依据。
|
|
|
|
|
|
<br />
|
|
|
|
|
|
主要用途:
|
|
|
|
|
|
</p>
|
|
|
|
|
|
<p>
|
|
|
|
|
|
用于细分市场选择:帮助企业从多个细分市场中识别出最具有投资潜力和竞争优势的市场。
|
|
|
|
|
|
<br />
|
|
|
|
|
|
|
|
|
|
|
|
产品规划:基于SPAN分析结果,企业可以制定针对性的产品规划和市场策略。
|
|
|
|
|
|
<br />
|
|
|
|
|
|
|
|
|
|
|
|
资源配置:根据细分市场的优先级,合理分配企业资源,如研发、生产、营销等。
|
|
|
|
|
|
<br />
|
|
|
|
|
|
应用场景:
|
|
|
|
|
|
</p>
|
|
|
|
|
|
<p>
|
|
|
|
|
|
新产品上市前的市场调研和细分市场选择。
|
|
|
|
|
|
<br />
|
|
|
|
|
|
现有产品线的市场优化和再定位。
|
|
|
|
|
|
<br />
|
|
|
|
|
|
跨地域或跨行业的市场拓展策略制定。
|
|
|
|
|
|
<br />
|
|
|
|
|
|
</p>
|
|
|
|
|
|
<div class="caseBacktitle">
|
|
|
|
|
|
<img src="@/assets/images/步骤.png" alt="" />
|
|
|
|
|
|
<span>二、实验实训</span>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<p>某电商商家主做服装鞋帽类产品,计划进入童装童鞋或者宠物服饰细分领域,想要通过SPAN定位模型来确定产品的市场定位,以提高市场竞争力和销售业绩,判断这两者哪个更适合进入。</p>
|
|
|
|
|
|
<el-table
|
|
|
|
|
|
:data="tableData"
|
|
|
|
|
|
border
|
|
|
|
|
|
style="width: 100%"
|
|
|
|
|
|
:header-cell-style="{
|
|
|
|
|
|
color: '#fff',
|
|
|
|
|
|
fontSize: '14px',
|
|
|
|
|
|
backgroundColor: '#6A7DE9!important',
|
|
|
|
|
|
}"
|
|
|
|
|
|
:span-method="arraySpanMethod"
|
|
|
|
|
|
>
|
|
|
|
|
|
<!-- 第一行合并的标题 -->
|
|
|
|
|
|
<el-table-column label="" prop="category" width="120" align="center">
|
|
|
|
|
|
<el-table-column label="细分领域" prop="category" width="120" align="center"></el-table-column>
|
|
|
|
|
|
</el-table-column>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 竞争地位评分 -->
|
|
|
|
|
|
<el-table-column label="竞争地位 (打分,满分10分)" align="center">
|
|
|
|
|
|
<el-table-column prop="techScore" label="技术" align="center">
|
|
|
|
|
|
<template #default="{ row }">
|
|
|
|
|
|
<el-input v-model="row.techScore" size="small"></el-input>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</el-table-column>
|
|
|
|
|
|
<el-table-column prop="marketShareScore" label="市场份额" align="center">
|
|
|
|
|
|
<template #default="{ row }">
|
|
|
|
|
|
<el-input v-model="row.marketShareScore" size="small"></el-input>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</el-table-column>
|
|
|
|
|
|
<el-table-column prop="brandScore" label="品牌" align="center">
|
|
|
|
|
|
<template #default="{ row }">
|
|
|
|
|
|
<el-input v-model="row.brandScore" size="small"></el-input>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</el-table-column>
|
|
|
|
|
|
<el-table-column prop="costScore" label="成本" align="center">
|
|
|
|
|
|
<template #default="{ row }">
|
|
|
|
|
|
<el-input v-model="row.costScore" size="small"></el-input>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</el-table-column>
|
|
|
|
|
|
</el-table-column>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 市场吸引力评分 -->
|
|
|
|
|
|
<el-table-column label="市场吸引力 (打分,满分10分)" align="center">
|
|
|
|
|
|
<el-table-column prop="entryBarrierScore" label="进入门槛" align="center">
|
|
|
|
|
|
<template #default="{ row }">
|
|
|
|
|
|
<el-input v-model="row.entryBarrierScore" size="small"></el-input>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</el-table-column>
|
|
|
|
|
|
<el-table-column prop="profitLevelScore" label="利润水平" align="center">
|
|
|
|
|
|
<template #default="{ row }">
|
|
|
|
|
|
<el-input v-model="row.profitLevelScore" size="small"></el-input>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</el-table-column>
|
|
|
|
|
|
<el-table-column prop="annualGrowthScore" label="年度增长" align="center">
|
|
|
|
|
|
<template #default="{ row }">
|
|
|
|
|
|
<el-input v-model="row.annualGrowthScore" size="small"></el-input>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</el-table-column>
|
|
|
|
|
|
<el-table-column prop="marketSizeScore" label="规模" align="center">
|
|
|
|
|
|
<template #default="{ row }">
|
|
|
|
|
|
<el-input v-model="row.marketSizeScore" size="small"></el-input>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</el-table-column>
|
|
|
|
|
|
</el-table-column>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 竞争地位权重 -->
|
|
|
|
|
|
<el-table-column label="竞争地位 (权重)" align="center">
|
|
|
|
|
|
<el-table-column prop="techWeight" label="技术" align="center"></el-table-column>
|
|
|
|
|
|
<el-table-column prop="marketShareWeight" label="市场份额" align="center"></el-table-column>
|
|
|
|
|
|
<el-table-column prop="brandWeight" label="品牌" align="center"></el-table-column>
|
|
|
|
|
|
<el-table-column prop="costWeight" label="成本" align="center"></el-table-column>
|
|
|
|
|
|
</el-table-column>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 市场吸引力权重 -->
|
|
|
|
|
|
<el-table-column label="市场吸引力 (权重)" align="center">
|
|
|
|
|
|
<el-table-column prop="entryBarrierWeight" label="进入门槛" align="center"></el-table-column>
|
|
|
|
|
|
<el-table-column prop="profitLevelWeight" label="利润水平" align="center"></el-table-column>
|
|
|
|
|
|
<el-table-column prop="annualGrowthWeight" label="年度增长" align="center"></el-table-column>
|
|
|
|
|
|
<el-table-column prop="marketSizeWeight" label="规模" align="center"></el-table-column>
|
|
|
|
|
|
</el-table-column>
|
|
|
|
|
|
<el-table-column label="竞争地位" align="center" prop="competitivePosition"></el-table-column>
|
|
|
|
|
|
<el-table-column label="市场吸引力" align="center" width="100" prop="marketAttractive"></el-table-column>
|
|
|
|
|
|
</el-table>
|
|
|
|
|
|
<p>
|
|
|
|
|
|
(一)竞争地位(满分10分):
|
|
|
|
|
|
<br />
|
|
|
|
|
|
1、技术(领先:10分;跟随:7分;一般:4分;低:1分);
|
|
|
|
|
|
<br />
|
|
|
|
|
|
2、市场份额(前三:10分;前十:7分;前三十:4分;后:1分);
|
|
|
|
|
|
<br />
|
|
|
|
|
|
3、品牌(前三:10分;前十:7分;前三十:4分;后:1分);
|
|
|
|
|
|
<br />
|
|
|
|
|
|
4、成本(最低:10分;较低:7分;中等:4分;较高:1分)。
|
|
|
|
|
|
<br />
|
|
|
|
|
|
</p>
|
|
|
|
|
|
<p>
|
|
|
|
|
|
(二)市场吸引力(满分10分):
|
|
|
|
|
|
<br />
|
|
|
|
|
|
1、进入门槛(很高:10分;较高:7分;一般:5分;较低:2分;很低:1分);
|
|
|
|
|
|
<br />
|
|
|
|
|
|
2、利润水平(20%:10分;15%:7分;10%:5分;5%:2分);
|
|
|
|
|
|
<br />
|
|
|
|
|
|
3、年度增长(30%:10分;20%:7分;15%:5分;10%:2分);
|
|
|
|
|
|
<br />
|
|
|
|
|
|
4、规模(按照预估市场规模直接转换分数)。
|
|
|
|
|
|
</p>
|
|
|
|
|
|
<p>请根据数据分析、调研结果及个人判断完善上表并根据上述打分说明进行打分,其中权重部分可进行修改。完成后请进行图形可视化绘制,查看童装童鞋及宠物服饰市场定位情况。</p>
|
|
|
|
|
|
<div style="display: flex; gap: 40px">
|
|
|
|
|
|
<div>
|
|
|
|
|
|
<span>童装童鞋SPAN分析评分:</span>
|
|
|
|
|
|
<div style="display: flex; gap: 40px" class="ptb10">
|
|
|
|
|
|
<div class="online">
|
|
|
|
|
|
<span>竞争地位评分:</span>
|
|
|
|
|
|
<el-input style="width: 100px" type="text" v-model="formInline.range1" />
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="online">
|
|
|
|
|
|
<span>市场吸引力评分:</span>
|
|
|
|
|
|
<el-input style="width: 100px" type="text" v-model="formInline.range2" />
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div>
|
|
|
|
|
|
<span>宠物服饰SPAN分析评分:</span>
|
|
|
|
|
|
<div style="display: flex; gap: 40px" class="ptb10">
|
|
|
|
|
|
<div class="online">
|
|
|
|
|
|
<span>竞争地位评分:</span>
|
|
|
|
|
|
<el-input style="width: 100px" type="text" v-model="formInline.range3" />
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="online">
|
|
|
|
|
|
<span>市场吸引力评分:</span>
|
|
|
|
|
|
<el-input style="width: 100px" type="text" v-model="formInline.range4" />
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<el-button class="ml20" @click="getinit">绘制</el-button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div ref="chart" style="width: 50%; height: 500px"></div>
|
|
|
|
|
|
<p>请阐述你关于童装童鞋和宠物服饰细分市场各项指标权重设置及打分依据,针对图形可视化结果进行分析说明,并给出下一步决策。</p>
|
|
|
|
|
|
<el-input v-model="formInline.textarea2" :autosize="{ minRows: 11, maxRows: 11 }" type="textarea" placeholder="" />
|
|
|
|
|
|
<div class="taskfooter">
|
|
|
|
|
|
<el-button @click="submitTask">提交任务</el-button>
|
|
|
|
|
|
<el-button @click="resetTask">重新实训</el-button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
<script setup>
|
|
|
|
|
|
import * as analysisAPI from "@/api/market-demand-mining.js";
|
|
|
|
|
|
import * as echarts from "echarts";
|
|
|
|
|
|
import popModel from "@/views/components/popModal.vue";
|
|
|
|
|
|
const { proxy } = getCurrentInstance();
|
|
|
|
|
|
import useUserStore from "@/store/modules/user";
|
|
|
|
|
|
const userStore = useUserStore();
|
|
|
|
|
|
const dialogVisible = ref(false);
|
|
|
|
|
|
const chart = ref(null);
|
|
|
|
|
|
const formInline = ref({
|
|
|
|
|
|
range1: "",
|
|
|
|
|
|
range2: "",
|
|
|
|
|
|
range3: "",
|
|
|
|
|
|
range4: "",
|
|
|
|
|
|
textarea2: "",
|
|
|
|
|
|
});
|
|
|
|
|
|
const tableData = ref([
|
|
|
|
|
|
{
|
|
|
|
|
|
category: "童装童鞋",
|
|
|
|
|
|
techScore: 0,
|
|
|
|
|
|
marketShareScore: 0,
|
|
|
|
|
|
brandScore: 0,
|
|
|
|
|
|
costScore: 0,
|
|
|
|
|
|
entryBarrierScore: 0,
|
|
|
|
|
|
profitLevelScore: 0,
|
|
|
|
|
|
annualGrowthScore: 0,
|
|
|
|
|
|
marketSizeScore: 0,
|
|
|
|
|
|
techWeight: "25%",
|
|
|
|
|
|
marketShareWeight: "25%",
|
|
|
|
|
|
brandWeight: "25%",
|
|
|
|
|
|
costWeight: "25%",
|
|
|
|
|
|
entryBarrierWeight: "25%",
|
|
|
|
|
|
profitLevelWeight: "25%",
|
|
|
|
|
|
annualGrowthWeight: "25%",
|
|
|
|
|
|
marketSizeWeight: "25%",
|
|
|
|
|
|
competitivePosition: "50%",
|
|
|
|
|
|
marketAttractive: "50%",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
category: "宠物服饰",
|
|
|
|
|
|
techScore: 0,
|
|
|
|
|
|
marketShareScore: 0,
|
|
|
|
|
|
brandScore: 0,
|
|
|
|
|
|
costScore: 0,
|
|
|
|
|
|
entryBarrierScore: 0,
|
|
|
|
|
|
profitLevelScore: 0,
|
|
|
|
|
|
annualGrowthScore: 0,
|
|
|
|
|
|
marketSizeScore: 0,
|
|
|
|
|
|
techWeight: "25%",
|
|
|
|
|
|
marketShareWeight: "25%",
|
|
|
|
|
|
brandWeight: "25%",
|
|
|
|
|
|
costWeight: "25%",
|
|
|
|
|
|
entryBarrierWeight: "25%",
|
|
|
|
|
|
profitLevelWeight: "25%",
|
|
|
|
|
|
annualGrowthWeight: "25%",
|
|
|
|
|
|
marketSizeWeight: "25%",
|
|
|
|
|
|
competitivePosition: "50%",
|
|
|
|
|
|
marketAttractive: "50%",
|
|
|
|
|
|
},
|
|
|
|
|
|
]);
|
|
|
|
|
|
const data = ref([
|
|
|
|
|
|
{ name: "童装童鞋", competition: 0, attraction: 0 },
|
|
|
|
|
|
{ name: "宠物服饰", competition: 0, attraction: 0 },
|
|
|
|
|
|
]);
|
|
|
|
|
|
// 更新data数组的方法
|
|
|
|
|
|
const updateData = () => {
|
|
|
|
|
|
data.value = [
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "童装童鞋",
|
|
|
|
|
|
competition: parseFloat(formInline.value.range1) || 0, // 转换为数字,如果为空则设为0
|
|
|
|
|
|
attraction: parseFloat(formInline.value.range2) || 0,
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "宠物服饰",
|
|
|
|
|
|
competition: parseFloat(formInline.value.range3) || 0,
|
|
|
|
|
|
attraction: parseFloat(formInline.value.range4) || 0,
|
|
|
|
|
|
},
|
|
|
|
|
|
];
|
|
|
|
|
|
};
|
|
|
|
|
|
const getinit = () => {
|
|
|
|
|
|
var myChart = echarts.init(chart.value);
|
|
|
|
|
|
// 准备散点图数据
|
|
|
|
|
|
updateData();
|
|
|
|
|
|
const scatterData = data.value.map((item) => ({
|
|
|
|
|
|
name: item.name,
|
|
|
|
|
|
value: [item.competition, item.attraction],
|
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
|
|
myChart.setOption({
|
|
|
|
|
|
title: {
|
|
|
|
|
|
text: "战略地位分析(SPAN模型)",
|
|
|
|
|
|
left: "center",
|
|
|
|
|
|
},
|
|
|
|
|
|
tooltip: {
|
|
|
|
|
|
formatter: function (params) {
|
|
|
|
|
|
const x = params.value[0];
|
|
|
|
|
|
const y = params.value[1];
|
|
|
|
|
|
return `
|
|
|
|
|
|
<div style="font-weight:bold">${params.name}</div>
|
|
|
|
|
|
<div>竞争地位: ${x}</div>
|
|
|
|
|
|
<div>市场吸引力: ${y}</div>
|
|
|
|
|
|
`;
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
xAxis: {
|
|
|
|
|
|
name: "竞争地位",
|
|
|
|
|
|
min: 0,
|
|
|
|
|
|
max: 10,
|
|
|
|
|
|
splitLine: {
|
|
|
|
|
|
show: true,
|
|
|
|
|
|
lineStyle: {
|
|
|
|
|
|
type: "dashed",
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
axisLine: {
|
|
|
|
|
|
lineStyle: {
|
|
|
|
|
|
color: "#333",
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
axisLabel: {
|
|
|
|
|
|
formatter: "{value}",
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
yAxis: {
|
|
|
|
|
|
name: "市场吸引力",
|
|
|
|
|
|
min: 0,
|
|
|
|
|
|
max: 10,
|
|
|
|
|
|
splitLine: {
|
|
|
|
|
|
show: true,
|
|
|
|
|
|
lineStyle: {
|
|
|
|
|
|
type: "dashed",
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
axisLine: {
|
|
|
|
|
|
lineStyle: {
|
|
|
|
|
|
color: "#333",
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
axisLabel: {
|
|
|
|
|
|
formatter: "{value}",
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
series: [
|
|
|
|
|
|
{
|
|
|
|
|
|
// 添加中轴线
|
|
|
|
|
|
type: "line",
|
|
|
|
|
|
markLine: {
|
|
|
|
|
|
silent: true,
|
|
|
|
|
|
symbol: "none",
|
|
|
|
|
|
lineStyle: {
|
|
|
|
|
|
color: "#333",
|
|
|
|
|
|
width: 1,
|
|
|
|
|
|
},
|
|
|
|
|
|
data: [
|
|
|
|
|
|
{ xAxis: 5 }, // 垂直中线
|
|
|
|
|
|
{ yAxis: 5 }, // 水平中线
|
|
|
|
|
|
],
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "数据点",
|
|
|
|
|
|
type: "scatter",
|
|
|
|
|
|
data: scatterData,
|
|
|
|
|
|
symbolSize: 20,
|
|
|
|
|
|
itemStyle: {
|
|
|
|
|
|
color: function (params) {
|
|
|
|
|
|
// 根据不同的数据点设置不同颜色
|
|
|
|
|
|
return params.data.name === "童装童鞋" ? "#ee6666" : "#5470c6";
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
label: {
|
|
|
|
|
|
show: true,
|
|
|
|
|
|
position: "top",
|
|
|
|
|
|
formatter: "{b}",
|
|
|
|
|
|
},
|
|
|
|
|
|
emphasis: {
|
|
|
|
|
|
label: {
|
|
|
|
|
|
show: true,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
],
|
|
|
|
|
|
grid: {
|
|
|
|
|
|
left: "10%",
|
|
|
|
|
|
right: "10%",
|
|
|
|
|
|
bottom: "10%",
|
|
|
|
|
|
containLabel: true,
|
|
|
|
|
|
},
|
|
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
const validateForm = () => {
|
|
|
|
|
|
const isComplete = tableData.value.every((item) => {
|
|
|
|
|
|
return [item.techScore, item.marketShareScore, item.brandScore, item.costScore, item.entryBarrierScore, item.profitLevelScore, item.annualGrowthScore, item.marketSizeScore].every((score) => score !== 0);
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
if (!isComplete) {
|
|
|
|
|
|
proxy.$modal.msgWarning("请完成所有评分字段的填写");
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
return true;
|
|
|
|
|
|
};
|
|
|
|
|
|
const submitTask = () => {
|
|
|
|
|
|
if (!validateForm()) return; // 验证表单是否填写完整
|
|
|
|
|
|
// 判断是否填写完整
|
|
|
|
|
|
if (formInline.value.range1 == "" || formInline.value.range2 == "") {
|
|
|
|
|
|
proxy.$modal.msgWarning("请填写竞争地位评分和市场吸引力评分!");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
let params = {
|
|
|
|
|
|
userId: userStore.userInfo.userId,
|
|
|
|
|
|
competitivePositionScore: formInline.value.range1,
|
|
|
|
|
|
marketAttractivenessScore: formInline.value.range2,
|
|
|
|
|
|
context: formInline.value.textarea2,
|
|
|
|
|
|
competitivePosition: JSON.stringify(tableData.value),
|
|
|
|
|
|
};
|
|
|
|
|
|
analysisAPI
|
|
|
|
|
|
.productDifferentiationSubmit(params)
|
|
|
|
|
|
.then((res) => {
|
|
|
|
|
|
proxy.$modal.msgSuccess("提交成功");
|
|
|
|
|
|
loadTaskInfo();
|
|
|
|
|
|
})
|
|
|
|
|
|
.catch((err) => {
|
|
|
|
|
|
proxy.$modal.msgError(err.message);
|
|
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
// 回显数据
|
|
|
|
|
|
const loadTaskInfo = () => {
|
|
|
|
|
|
analysisAPI
|
|
|
|
|
|
.productDifferentiationEcho({
|
|
|
|
|
|
userId: userStore.userInfo.userId,
|
|
|
|
|
|
})
|
|
|
|
|
|
.then((res) => {
|
|
|
|
|
|
if (!res.data) return;
|
|
|
|
|
|
formInline.value.range1 = res.data.competitivePositionScore;
|
|
|
|
|
|
formInline.value.range2 = res.data.marketAttractivenessScore;
|
|
|
|
|
|
formInline.value.textarea2 = res.data.context;
|
|
|
|
|
|
tableData.value = JSON.parse(res.data.competitivePosition);
|
|
|
|
|
|
if (formInline.value.range1 && formInline.value.range2) {
|
|
|
|
|
|
getinit();
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
const resetTask = () => {
|
|
|
|
|
|
analysisAPI
|
|
|
|
|
|
.productPricingReTrain({
|
|
|
|
|
|
userId: userStore.userInfo.userId,
|
|
|
|
|
|
module: "产品差异化定位",
|
|
|
|
|
|
})
|
|
|
|
|
|
.then((res) => {
|
|
|
|
|
|
proxy.$modal.msgSuccess("重新实训成功");
|
|
|
|
|
|
formInline.value.range1 = "";
|
|
|
|
|
|
formInline.value.range2 = "";
|
|
|
|
|
|
formInline.value.textarea2 = "";
|
|
|
|
|
|
// 重置表格数据
|
|
|
|
|
|
tableData.value = [
|
|
|
|
|
|
{
|
|
|
|
|
|
category: "童装童鞋",
|
|
|
|
|
|
techScore: 0,
|
|
|
|
|
|
marketShareScore: 0,
|
|
|
|
|
|
brandScore: 0,
|
|
|
|
|
|
costScore: 0,
|
|
|
|
|
|
entryBarrierScore: 0,
|
|
|
|
|
|
profitLevelScore: 0,
|
|
|
|
|
|
annualGrowthScore: 0,
|
|
|
|
|
|
marketSizeScore: 0,
|
|
|
|
|
|
techWeight: "25%",
|
|
|
|
|
|
marketShareWeight: "25%",
|
|
|
|
|
|
brandWeight: "25%",
|
|
|
|
|
|
costWeight: "25%",
|
|
|
|
|
|
entryBarrierWeight: "25%",
|
|
|
|
|
|
profitLevelWeight: "25%",
|
|
|
|
|
|
annualGrowthWeight: "25%",
|
|
|
|
|
|
marketSizeWeight: "25%",
|
|
|
|
|
|
competitivePosition: "50%",
|
|
|
|
|
|
marketAttractive: "50%",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
category: "宠物服饰",
|
|
|
|
|
|
techScore: 0,
|
|
|
|
|
|
marketShareScore: 0,
|
|
|
|
|
|
brandScore: 0,
|
|
|
|
|
|
costScore: 0,
|
|
|
|
|
|
entryBarrierScore: 0,
|
|
|
|
|
|
profitLevelScore: 0,
|
|
|
|
|
|
annualGrowthScore: 0,
|
|
|
|
|
|
marketSizeScore: 0,
|
|
|
|
|
|
techWeight: "25%",
|
|
|
|
|
|
marketShareWeight: "25%",
|
|
|
|
|
|
brandWeight: "25%",
|
|
|
|
|
|
costWeight: "25%",
|
|
|
|
|
|
entryBarrierWeight: "25%",
|
|
|
|
|
|
profitLevelWeight: "25%",
|
|
|
|
|
|
annualGrowthWeight: "25%",
|
|
|
|
|
|
marketSizeWeight: "25%",
|
|
|
|
|
|
},
|
|
|
|
|
|
];
|
|
|
|
|
|
// 重置散点图数据
|
|
|
|
|
|
scatterData.value = [
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "数据点",
|
|
|
|
|
|
value: [0, 0], // [x, y] 即 [竞争地位, 市场吸引力]
|
|
|
|
|
|
},
|
|
|
|
|
|
];
|
|
|
|
|
|
const myChart = echarts.init(chart.value);
|
|
|
|
|
|
myChart.setOption({
|
|
|
|
|
|
series: [
|
|
|
|
|
|
{
|
|
|
|
|
|
data: scatterData.value,
|
|
|
|
|
|
},
|
|
|
|
|
|
],
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
onMounted(() => {
|
|
|
|
|
|
loadTaskInfo();
|
|
|
|
|
|
});
|
|
|
|
|
|
</script>
|
|
|
|
|
|
<style lang='scss' scoped>
|
|
|
|
|
|
.differentiation {
|
|
|
|
|
|
background: #ffffff;
|
|
|
|
|
|
}
|
|
|
|
|
|
</style>
|