|
|
|
|
@ -1,7 +1,7 @@
|
|
|
|
|
<template>
|
|
|
|
|
<div class="main-top">
|
|
|
|
|
<span style="font-weight: bold; font-size: 18px; color: #3596eb">任务描述</span>
|
|
|
|
|
<p style="font-weight: 400; font-size: 12px; color: #e2e7ee !important">(给出任务清单参考,做哪些数据的统计分析)Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean euismod bibendum laoreet. Proin gravida dolor sit amet lacus accumsan et viverra justo commodo. Proin sodales pulvinar sic tempor. Sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Nam fermentum, nulla luctus pharetra vulputate, felis tellus mollis orci, sed rhoncus pronin sapien nunc accuan eget.</p>
|
|
|
|
|
<p style="font-weight: 400; font-size: 12px; color: #e2e7ee !important">使用“用户商品评论数据”,进行各类文本挖掘任务,分析评论情感情绪,最后提交实训任务。</p>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="main-but">
|
|
|
|
|
<el-button @click="knowledgeImport">
|
|
|
|
|
@ -69,11 +69,9 @@
|
|
|
|
|
<el-scrollbar height="550px" style="padding: 20px">
|
|
|
|
|
<div>
|
|
|
|
|
<span style="font-weight: bold; font-size: 18px; color: #3596eb">分析数据:</span>
|
|
|
|
|
<div class="text-type" v-show="preProcessText.text3 == '评论观点抽取'">
|
|
|
|
|
<el-button :class="s_commentType == text.id ? 'btnActive' : ''" v-for="text in textType" :key="text" type="primary" plain @click="commentType(text)">{{ text.name }}</el-button>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="analysis">
|
|
|
|
|
<el-input maxlength="256" show-word-limit v-model="g_analyzeTheNumberOfDataItems" :rows="2" type="textarea" placeholder="" />
|
|
|
|
|
<el-input v-model="g_analyzeTheNumberOfDataItems" :rows="2" type="textarea" placeholder="" />
|
|
|
|
|
</div>
|
|
|
|
|
<div class="footer">
|
|
|
|
|
<el-button type="primary" plain @click="sentimentAnalysis">情感分析</el-button>
|
|
|
|
|
@ -113,7 +111,8 @@
|
|
|
|
|
<span>正向情感</span>
|
|
|
|
|
<img src="../../../assets/images/笑脸.png" alt="" />
|
|
|
|
|
</div>
|
|
|
|
|
<el-progress :class="[g_emotionAnalysis == 0 ? 'negPercentage ' : '']" style="width: 480px" :text-inside="true" :stroke-width="20" :percentage="n_emotiveTendency" :color="'#ff540a'" />
|
|
|
|
|
|
|
|
|
|
<el-progress style="width: 480px" :text-inside="true" :stroke-width="20" :percentage="n_emotiveTendency" :color="'#ff540a'" />
|
|
|
|
|
<div class="emotion_analysis-ani-in-ri">
|
|
|
|
|
<img src="../../../assets/images/哭脸.png" alt="" />
|
|
|
|
|
<span>负向情感</span>
|
|
|
|
|
@ -126,7 +125,11 @@
|
|
|
|
|
<div class="result-pos" :class="sentiment == 0 ? 'result-neg' : sentiment == 1 ? 'result-neutral' : 'result-img'"></div>
|
|
|
|
|
<div class="result-title">{{ sentiment == 0 ? "负向评价" : sentiment == 1 ? "中性评价" : "正向评价" }}:</div>
|
|
|
|
|
<div class="result-view" v-for="items in item" :key="items">
|
|
|
|
|
{{ items.prop + items.adj }}
|
|
|
|
|
<span v-if="items.opinions.length == 0">{{ items.aspect }}</span>
|
|
|
|
|
<span v-for="i in items.opinions" :key="i">
|
|
|
|
|
{{ items.aspect + i }}
|
|
|
|
|
<div class="result-bar"></div>
|
|
|
|
|
</span>
|
|
|
|
|
<div class="result-bar"></div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
@ -145,7 +148,7 @@
|
|
|
|
|
</template>
|
|
|
|
|
<div class="from-item">
|
|
|
|
|
<el-form :inline="true" label-width="84px" :model="form" class="demo-form-inline">
|
|
|
|
|
<el-form-item label="平均数:" label-width="120px">
|
|
|
|
|
<el-form-item label="词频分析:" label-width="120px">
|
|
|
|
|
<el-form-item label="最多数量词语:" label-width="120px" label-position="left">
|
|
|
|
|
<el-input style="width: 140px" v-model="formInline.max" clearable />
|
|
|
|
|
</el-form-item>
|
|
|
|
|
@ -435,7 +438,7 @@ const multipleTableRef = ref(null);
|
|
|
|
|
const n_dataTableQuery = ref({
|
|
|
|
|
index: 1,
|
|
|
|
|
size: 5,
|
|
|
|
|
tableName: "用户属性表",
|
|
|
|
|
tableName: algorithmStore.userDataLabel2[0],
|
|
|
|
|
userId: userInfo.userId,
|
|
|
|
|
});
|
|
|
|
|
const textType = [
|
|
|
|
|
@ -456,9 +459,7 @@ const textType = [
|
|
|
|
|
const dialogVisible = ref(false);
|
|
|
|
|
const analysisData = ref([]);
|
|
|
|
|
const analysisHanderKry = ref([]);
|
|
|
|
|
//
|
|
|
|
|
const aWordFrequency = ref([]);
|
|
|
|
|
const s_commentType = ref("");
|
|
|
|
|
const tableLabel = reactive([
|
|
|
|
|
{ prop: "max", label: "最多数量词语" },
|
|
|
|
|
{ prop: "frequency", label: "频次" },
|
|
|
|
|
@ -490,7 +491,6 @@ const mWordFrequency = ref({
|
|
|
|
|
namenum: "",
|
|
|
|
|
frequency: "",
|
|
|
|
|
}); //词频数据
|
|
|
|
|
|
|
|
|
|
// 分析变量
|
|
|
|
|
const g_analyzeTheNumberOfDataItems = ref("");
|
|
|
|
|
// 模型参数
|
|
|
|
|
@ -500,7 +500,15 @@ const g_emotionAnalysis = ref(0);
|
|
|
|
|
const aCommentOpinion = ref([]);
|
|
|
|
|
// 下载状态
|
|
|
|
|
const downloadStatus = ref(false);
|
|
|
|
|
// 下载
|
|
|
|
|
//提交校验
|
|
|
|
|
const g_submitVerification = ref({
|
|
|
|
|
max: "13",
|
|
|
|
|
frequency: "3",
|
|
|
|
|
text1: "质量",
|
|
|
|
|
text2: "包装好",
|
|
|
|
|
emotional: "负向",
|
|
|
|
|
prominent: "的",
|
|
|
|
|
});
|
|
|
|
|
// 预处理
|
|
|
|
|
const preProcess = (tetx) => {
|
|
|
|
|
if (g_indicatorData.value.length == 0) {
|
|
|
|
|
@ -515,7 +523,11 @@ const preProcess = (tetx) => {
|
|
|
|
|
}).then((res) => {
|
|
|
|
|
proxy.$modal.msgSuccess("预处理成功");
|
|
|
|
|
analysisData.value = res.data;
|
|
|
|
|
g_analyzeTheNumberOfDataItems.value = res.data.map((item) => (item ? item.text : "")).join(",");
|
|
|
|
|
g_analyzeTheNumberOfDataItems.value = res.data
|
|
|
|
|
.slice(0, 4)
|
|
|
|
|
.map((item) => (item ? item.content : ""))
|
|
|
|
|
.join(",")
|
|
|
|
|
.replace(/\s+/g, "");
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
// 提交
|
|
|
|
|
@ -542,15 +554,19 @@ const submit = () => {
|
|
|
|
|
if (g_indicatorData.value.length == 0) return proxy.$modal.msgWarning("请选择指标");
|
|
|
|
|
loading.value = true;
|
|
|
|
|
marketingAlgorithmApi.getMarketingAlgorithm({ userId: n_dataTableQuery.value.userId, tableName: n_dataTableQuery.value.tableName, fieldList: g_indicatorData.value }).then((res) => {
|
|
|
|
|
// g_analyzeTheNumberOfDataItems.value =
|
|
|
|
|
if (
|
|
|
|
|
res.data
|
|
|
|
|
.map((item) => (item ? item.text : ""))
|
|
|
|
|
.map((item) => (item ? item.content : ""))
|
|
|
|
|
.every((item) => {
|
|
|
|
|
return item !== "";
|
|
|
|
|
})
|
|
|
|
|
) {
|
|
|
|
|
g_analyzeTheNumberOfDataItems.value = res.data.map((item) => (item ? item.text : "")).join(",");
|
|
|
|
|
g_analyzeTheNumberOfDataItems.value = res.data
|
|
|
|
|
.slice(0.4)
|
|
|
|
|
.map((item, index) => (item ? item.content : ""))
|
|
|
|
|
.slice(0, 4)
|
|
|
|
|
.join(",")
|
|
|
|
|
.replace(/\s+/g, "");
|
|
|
|
|
} else {
|
|
|
|
|
g_analyzeTheNumberOfDataItems.value = "";
|
|
|
|
|
loading.value = false;
|
|
|
|
|
@ -574,18 +590,26 @@ const knowledgeImport = () => {
|
|
|
|
|
};
|
|
|
|
|
// 实训任务提交
|
|
|
|
|
const submitTask = () => {
|
|
|
|
|
let flat = false;
|
|
|
|
|
for (let key in formInline.value) {
|
|
|
|
|
if (formInline.value[key] == "") {
|
|
|
|
|
const label = tableLabel.find((item) => item.prop == key);
|
|
|
|
|
proxy.$modal.msgWarning(`${label.label}不能为空`);
|
|
|
|
|
return;
|
|
|
|
|
} else {
|
|
|
|
|
if (formInline.value[key] != g_submitVerification.value[key]) {
|
|
|
|
|
const label = tableLabel.find((item) => item.prop == key);
|
|
|
|
|
proxy.$modal.msgWarning(`${label.label}错误`);
|
|
|
|
|
flat = true;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
portraitModel
|
|
|
|
|
.submit({
|
|
|
|
|
userId: n_dataTableQuery.value.userId,
|
|
|
|
|
taskName: "情感分析",
|
|
|
|
|
numberOfErrors: 0,
|
|
|
|
|
numberOfErrors: flat ? 1 : 0,
|
|
|
|
|
})
|
|
|
|
|
.then((res) => {
|
|
|
|
|
dialogVisible.value = false;
|
|
|
|
|
@ -624,7 +648,6 @@ const restart = () => {
|
|
|
|
|
nOriginalWordFrequencyNum.value = 0;
|
|
|
|
|
aWordFrequency.value = [];
|
|
|
|
|
nOriginalWordFrequency.value = [];
|
|
|
|
|
s_commentType.value = "";
|
|
|
|
|
proxy.$modal.msgSuccess("重新开始!");
|
|
|
|
|
multipleTableRef.value.clearSelection();
|
|
|
|
|
};
|
|
|
|
|
@ -637,12 +660,14 @@ const download = async () => {
|
|
|
|
|
try {
|
|
|
|
|
// 使用 html2canvas 将元素转换为画布
|
|
|
|
|
let VDOM = document.querySelector(".emotion_analysis_title");
|
|
|
|
|
let VDOM2 = document.querySelector(".result");
|
|
|
|
|
|
|
|
|
|
let VDOM2 = document.getElementsByClassName("result");
|
|
|
|
|
if (preProcessText.value.text3 == "情感倾向分析") {
|
|
|
|
|
VDOM.style.color = "#221f1f";
|
|
|
|
|
} else {
|
|
|
|
|
VDOM2.style.color = "#212020";
|
|
|
|
|
for (let i = 0; i < VDOM2.length; i++) {
|
|
|
|
|
const element = VDOM2[i];
|
|
|
|
|
element.style.color = "#221f1f";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
const canvas = await html2canvas(captureElement.value);
|
|
|
|
|
|
|
|
|
|
@ -657,7 +682,10 @@ const download = async () => {
|
|
|
|
|
if (preProcessText.value.text3 == "情感倾向分析") {
|
|
|
|
|
VDOM.style.color = "#ffffff";
|
|
|
|
|
} else {
|
|
|
|
|
VDOM2.style.color = "#ffffff";
|
|
|
|
|
for (let i = 0; i < VDOM2.length; i++) {
|
|
|
|
|
const element = VDOM2[i];
|
|
|
|
|
element.style.color = "#ffffff";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error("无法生成图片", error);
|
|
|
|
|
@ -681,9 +709,7 @@ const sentimentAnalysis = () => {
|
|
|
|
|
if (preProcessText.value.text2 == "") return proxy.$modal.msgWarning("请先对数据进行预处理!");
|
|
|
|
|
}
|
|
|
|
|
if (preProcessText.value.text3 == "") return proxy.$modal.msgWarning("请先选择模型!");
|
|
|
|
|
if (preProcessText.value.text3 === "评论观点抽取" && s_commentType.value == "") {
|
|
|
|
|
return proxy.$modal.msgWarning("请先选择评论类型!");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (g_analyzeTheNumberOfDataItems.value == "") return proxy.$modal.msgWarning("请先选择指标/手动输入进行情感分析!");
|
|
|
|
|
loading.value = true;
|
|
|
|
|
if (preProcessText.value.text3 === "情感倾向分析") {
|
|
|
|
|
@ -698,23 +724,25 @@ const sentimentAnalysis = () => {
|
|
|
|
|
const negPercentage = total !== 0 ? (neg / total) * 100 : 0;
|
|
|
|
|
if (posPercentage > negPercentage) {
|
|
|
|
|
g_emotionAnalysis.value = 2;
|
|
|
|
|
n_emotiveTendency.value = posPercentage;
|
|
|
|
|
n_emotiveTendency.value = Math.floor(posPercentage);
|
|
|
|
|
} else if (negPercentage > posPercentage) {
|
|
|
|
|
g_emotionAnalysis.value = 0;
|
|
|
|
|
n_emotiveTendency.value = negPercentage;
|
|
|
|
|
n_emotiveTendency.value = Math.floor(posPercentage);
|
|
|
|
|
}
|
|
|
|
|
if (posPercentage == negPercentage) {
|
|
|
|
|
g_emotionAnalysis.value = 1;
|
|
|
|
|
n_emotiveTendency.value = 50;
|
|
|
|
|
}
|
|
|
|
|
loading.value = false;
|
|
|
|
|
downloadStatus.value = true;
|
|
|
|
|
proxy.$modal.msgSuccess("分析成功");
|
|
|
|
|
})
|
|
|
|
|
.catch((err) => {
|
|
|
|
|
loading.value = false;
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
} else if (preProcessText.value.text3 !== "评论观点抽取") {
|
|
|
|
|
marketingAlgorithmApi
|
|
|
|
|
.getMarketingAlgorithmSentiment({ id: s_commentType.value, userId: n_dataTableQuery.value.userId, content: g_analyzeTheNumberOfDataItems.value, modelType: preProcessText.value.text3 == "词云生成" ? "词频分析" : preProcessText.value.text3 })
|
|
|
|
|
.getMarketingAlgorithmSentiment({ userId: n_dataTableQuery.value.userId, content: g_analyzeTheNumberOfDataItems.value, modelType: preProcessText.value.text3 == "词云生成" ? "词频分析" : preProcessText.value.text3 })
|
|
|
|
|
.then((res) => {
|
|
|
|
|
if (preProcessText.value.text3 === "词云生成") {
|
|
|
|
|
nOriginalWordFrequency.value = res.data;
|
|
|
|
|
@ -723,18 +751,33 @@ const sentimentAnalysis = () => {
|
|
|
|
|
nOriginalWordFrequency.value = res.data;
|
|
|
|
|
aWordFrequency.value = res.data.slice(0, 5);
|
|
|
|
|
nOriginalWordFrequencyNum.value = res.data.length;
|
|
|
|
|
} else {
|
|
|
|
|
aCommentOpinion.value = JSON.parse(res.data).items.reduce((groups, item) => {
|
|
|
|
|
// 如果该 sentiment 的组不存在,则创建
|
|
|
|
|
if (!groups[item.sentiment]) {
|
|
|
|
|
groups[item.sentiment] = [];
|
|
|
|
|
}
|
|
|
|
|
// 将 item 加入到相应的组中
|
|
|
|
|
groups[item.sentiment].push(item);
|
|
|
|
|
return groups;
|
|
|
|
|
}, {});
|
|
|
|
|
}
|
|
|
|
|
downloadStatus.value = true;
|
|
|
|
|
g_submitVerification.value.n_maximumQuantity = nOriginalWordFrequency.value.reduce((longest, current) => {
|
|
|
|
|
return current.keyword.length > longest.keyword.length ? current.keyword : longest.keyword;
|
|
|
|
|
}, nOriginalWordFrequency.value[0]);
|
|
|
|
|
g_submitVerification.value.n_frequency = nOriginalWordFrequency.value.reduce((longest, current) => {
|
|
|
|
|
return item.frequency > max.frequency ? item.n_frequency : max.n_frequency;
|
|
|
|
|
}, nOriginalWordFrequency.value[0]);
|
|
|
|
|
console.log(g_submitVerification.value, "g_submitVerification.value.");
|
|
|
|
|
loading.value = false;
|
|
|
|
|
proxy.$modal.msgSuccess("分析成功");
|
|
|
|
|
})
|
|
|
|
|
.catch((err) => {
|
|
|
|
|
loading.value = false;
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
portraitModel
|
|
|
|
|
.getCommentPoint(JSON.stringify({ text: g_analyzeTheNumberOfDataItems.value }))
|
|
|
|
|
.then((res) => {
|
|
|
|
|
aCommentOpinion.value = res.singleAnalysisResult.reduce((groups, item) => {
|
|
|
|
|
if (!groups[item.sentiment == "正向" ? 2 : 0]) {
|
|
|
|
|
groups[item.sentiment == "正向" ? 2 : 0] = [];
|
|
|
|
|
}
|
|
|
|
|
groups[item.sentiment == "正向" ? 2 : 0].push(item);
|
|
|
|
|
return groups;
|
|
|
|
|
}, {});
|
|
|
|
|
downloadStatus.value = true;
|
|
|
|
|
loading.value = false;
|
|
|
|
|
proxy.$modal.msgSuccess("分析成功");
|
|
|
|
|
})
|
|
|
|
|
@ -748,6 +791,7 @@ const clear = () => {
|
|
|
|
|
if (!g_analyzeTheNumberOfDataItems.value) return proxy.$modal.msgWarning("请先分析数据!");
|
|
|
|
|
g_analyzeTheNumberOfDataItems.value = "";
|
|
|
|
|
aWordFrequency.value = [];
|
|
|
|
|
loading.value = false;
|
|
|
|
|
proxy.$modal.msgSuccess("清空成功");
|
|
|
|
|
};
|
|
|
|
|
const initChart = () => {
|
|
|
|
|
@ -814,9 +858,7 @@ const initChart = () => {
|
|
|
|
|
],
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
const commentType = (text) => {
|
|
|
|
|
s_commentType.value = text.id;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const wordFrequencyNext = () => {
|
|
|
|
|
if (mWordFrequency.value.frequency !== "" || mWordFrequency.value.namenum !== "") {
|
|
|
|
|
wordFrequencySearch();
|
|
|
|
|
@ -849,7 +891,6 @@ const switchingModels = () => {
|
|
|
|
|
mWordFrequency.value.size = 5;
|
|
|
|
|
mWordFrequency.value.frequency = "";
|
|
|
|
|
mWordFrequency.value.namenum = "";
|
|
|
|
|
s_commentType.value = "";
|
|
|
|
|
};
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
@ -1198,4 +1239,8 @@ p {
|
|
|
|
|
border-color: #6fa8de !important;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
p,
|
|
|
|
|
h4 {
|
|
|
|
|
color: #ffffff;
|
|
|
|
|
}
|
|
|
|
|
</style>
|
|
|
|
|
|