完成情感分析

dev-QQq
qinzhenpen 2 years ago
parent 994c5f7164
commit 4facc5ef53

@ -16,16 +16,18 @@
},
"dependencies": {
"@antv/g2": "^5.2.3",
"echarts-stat": "^1.2.0",
"@element-plus/icons-vue": "2.0.10",
"@vueup/vue-quill": "1.1.0",
"@vueuse/core": "9.5.0",
"axios": "0.27.2",
"echarts": "5.4.0",
"echarts-stat": "^1.2.0",
"echarts-wordcloud": "^2.1.0",
"element-plus": "2.2.27",
"file-saver": "2.0.5",
"fuse.js": "6.6.2",
"highlight.js": "^11.10.0",
"html2canvas": "^1.4.1",
"js-cookie": "3.0.1",
"jsencrypt": "3.3.1",
"marked": "^14.0.0",
@ -34,7 +36,8 @@
"pinia": "2.0.22",
"vue": "^3.2.47",
"vue-cropper": "1.0.3",
"vue-router": "4.1.4"
"vue-router": "4.1.4",
"xlsx": "^0.18.5"
},
"devDependencies": {
"@vitejs/plugin-vue": "3.1.0",

Binary file not shown.

After

Width:  |  Height:  |  Size: 660 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 470 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1010 B

@ -2,22 +2,8 @@
<div>
<template v-for="(item, index) in options">
<template v-if="values.includes(item.value)">
<span
v-if="item.elTagType == 'default' || item.elTagType == ''"
:key="item.value"
:index="index"
:class="item.elTagClass"
>{{ item.label + " " }}</span
>
<el-tag
v-else
:disable-transitions="true"
:key="item.value + ''"
:index="index"
:type="item.elTagType === 'primary' ? '' : item.elTagType"
:class="item.elTagClass"
>{{ item.label + " " }}</el-tag
>
<span v-if="item.elTagType == 'default' || item.elTagType == ''" :key="item.value" :index="index" :class="item.elTagClass">{{ item.label + " " }}</span>
<el-tag v-else :disable-transitions="true" :key="item.value + ''" :index="index" :type="item.elTagType === 'primary' ? '' : item.elTagType" :class="item.elTagClass">{{ item.label + " " }}</el-tag>
</template>
</template>
<template v-if="unmatch && showValue">
@ -64,8 +50,7 @@ const unmatch = computed(() => {
}
// Array
props.value.forEach((item) => {
if (!props.options.some((v) => v.value == item))
unmatchArray.value.push(item);
if (!props.options.some((v) => v.value == item)) unmatchArray.value.push(item);
});
return true;
}
@ -85,4 +70,4 @@ function handleArray(array) {
.el-tag + .el-tag {
margin-left: 10px;
}
</style>
</style>

@ -0,0 +1,36 @@
export default {
beforeMount(el, { value, arg }) {
// 确保 binding.value 是一个函数
if (typeof value !== "function") {
console.warn("v-debounce directive requires a function as its value");
return;
}
// 默认防抖延迟为 300ms或使用传递的延迟值
const delay = Number(arg) || 300;
const debouncedFunction = debounce(value, delay);
// 事件处理器
const handler = (event) => {
debouncedFunction(event.target.value);
};
// 添加输入事件监听
el.addEventListener("input", handler);
// 保存销毁函数
el.$destroyDebounce = () => el.removeEventListener("input", handler);
},
unmounted(el) {
// 清理事件监听
if (el.$destroyDebounce) {
el.$destroyDebounce();
}
},
};
function debounce(func, delay) {
let timer;
return function (...args) {
clearTimeout(timer);
timer = setTimeout(() => func.apply(this, args), delay);
};
}

@ -1,9 +1,19 @@
/*
* @Author: qinzhenpen qzp1807@126.com
* @Date: 2024-07-15 15:44:46
* @LastEditors: qinzhenpen qzp1807@126.com
* @LastEditTime: 2024-08-20 15:53:35
* @FilePath: \vue3\src\directive\index.js
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import hasRole from './permission/hasRole'
import hasPermi from './permission/hasPermi'
import copyText from './common/copyText'
import debounce from './common/debounce'
export default function directive(app){
app.directive('hasRole', hasRole)
app.directive('hasPermi', hasPermi)
app.directive('copyText', copyText)
app.directive('debounce', debounce)
}

@ -16,8 +16,8 @@ axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'
const service = axios.create({
// axios中请求配置有baseURL选项表示请求URL公共部分
// baseURL: import.meta.env.VITE_APP_BASE_API,
baseURL:'http://118.31.7.2:9868/',
// baseURL:'http://192.168.2.28:9868/',
// baseURL:'http://118.31.7.2:9868/',
baseURL:'http://192.168.2.28:9868/',
// 超时
timeout: 100000
})

@ -354,7 +354,7 @@ onMounted(() => {
});
//
const getIndicator = () => {
algorithmStore.getUserDatabase({ userId: n_dataTableQuery.value.userId, tableName: n_dataTableQuery.value.tableName });
algorithmStore.getUserDatabase({ userId: n_dataTableQuery.value.userId, tableName: n_dataTableQuery.value.tableName, algorithmName: "描述性统计" });
};
//
const knowledgeImport = () => {

@ -49,13 +49,13 @@
<span>模型参数设置</span>
</div>
<div class="metrics-table" style="margin-top: 10px">
<el-select v-model="preProcessText.text3" placeholder="请选择模型" style="width: 180px" @change="preProcess">
<el-select v-model="preProcessText.text3" placeholder="请选择模型" style="width: 180px" @change="switchingModels">
<el-option label="评论观点抽取" value="评论观点抽取" />
<el-option label="情感倾向分析" value="情感倾向分析" />
<el-option label="词频分析" value="词频分析" />
<el-option label="词云生成" value="词云生成" />
</el-select>
<el-button @click="modelCalculation"></el-button>
<el-button @click="sentimentAnalysis"></el-button>
</div>
</div>
<div style="margin-top: auto">
@ -65,45 +65,77 @@
</div>
</div>
</div>
<div class="main-right">
<div>
<span style="font-weight: bold; font-size: 18px; color: #3596eb">分析数据</span>
<div class="text-type" v-show="preProcessText.text3 == '评论观点抽取'">
<el-button v-for="text in textType" :key="text" type="primary" plain>{{ text }}</el-button>
</div>
<div class="analysis">
<el-input v-model="g_analyzeTheNumberOfDataItems" :rows="2" type="textarea" placeholder="" />
</div>
<div class="footer">
<el-button type="primary" plain @click="sentimentAnalysis"></el-button>
<el-button type="primary" plain>清空</el-button>
<div class="main-right" v-loading="loading" :element-loading-spinner="svg" element-loading-svg-view-box="-10, -10, 50, 50" element-loading-background="rgba(122, 122, 122, 0.8)">
<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="" />
</div>
<div class="footer">
<el-button type="primary" plain @click="sentimentAnalysis"></el-button>
<el-button type="primary" plain @click="clear"></el-button>
</div>
</div>
</div>
<div class="analysisResults" style="margin-top: 20px">
<span style="font-weight: bold; font-size: 18px; color: #3596eb; display: block">分析结果</span>
<el-button @click="download"></el-button>
<h4>词频列表</h4>
<p>你可以对词频词语进行修改删除以及增加频次数越大显示越大最多200关键词</p>
<div class="conditions">
<label>显示条件:</label>
<div>
<span>频次>=</span>
<el-input v-model="input" style="width: 120px" placeholder="" />
<div class="analysisResults" style="margin-top: 20px">
<span style="font-weight: bold; font-size: 18px; color: #3596eb; display: block">分析结果</span>
<el-button @click="download"></el-button>
<div v-show="preProcessText.text3 == '词频分析'" v-loading="loading2" :element-loading-spinner="svg" element-loading-svg-view-box="-10, -10, 50, 50" element-loading-background="rgba(122, 122, 122, 0.8)">
<h4>词频列表</h4>
<p>你可以对词频词语进行修改删除以及增加频次数越大显示越大最多200关键词</p>
<div class="conditions">
<label>显示条件:</label>
<div>
<span>频次>=</span>
<el-input v-model="mWordFrequency.frequency" style="width: 120px" placeholder="" v-debounce="wordFrequencySearch" />
</div>
<div>
<span>词语长度>=</span>
<el-input v-model="mWordFrequency.namenum" style="width: 120px" placeholder="" v-debounce="wordFrequencySearch" />
</div>
</div>
<el-table border :data="aWordFrequency" style="width: 80%" :header-cell-style="headerCellStyle">
<el-table-column :label="`内容(${aWordFrequency?.length || 0})`" align="center" prop="keyword" width="747" />
<el-table-column label="频次" align="center" prop="frequency" />
</el-table>
<pagination :autoScroll="false" v-show="nOriginalWordFrequencyNum > 0" :total="nOriginalWordFrequencyNum" v-model:page="mWordFrequency.index" v-model:limit="mWordFrequency.size" @pagination="wordFrequencyNext" />
</div>
<!-- v-show="preProcessText.text3 == '词云生成'" -->
<div class="div" v-if="preProcessText.text3 == '词云生成'">
<div id="mywordcloud_positive" style="width: 50%; height: 600px"></div>
</div>
<div>
<span>词语长度>=</span>
<el-input v-model="input" style="width: 120px" placeholder="" />
<div ref="captureElement" v-if="preProcessText.text3 == '情感倾向分析' && n_emotiveTendency">
<div class="emotion_analysis">
<div class="emotion_analysis-ani-in-le">
<span>正向情感</span>
<img src="../../../assets/images/笑脸.png" alt="" />
</div>
<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="" alt="" />
<span>负向情感</span>
</div>
<div class="emotion_analysis_title">{{ g_emotionAnalysis == 0 ? "情感偏负向" : g_emotionAnalysis == 1 ? "情感偏中性" : "情感偏正向" }}</div>
</div>
</div>
<div ref="captureElement" class="comment-opinion" v-if="preProcessText.text3 == '评论观点抽取'">
<div class="result" v-for="(item, sentiment) in aCommentOpinion" :key="item.abstract">
<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 }}
<div class="result-bar"></div>
</div>
</div>
</div>
</div>
<el-table border :data="aWordFrequency" style="width: 80%" :header-cell-style="headerCellStyle">
<el-table-column label="内容5" align="center" prop="keyword" width="747"/>
<el-table-column label="频次" align="center" prop="frequency" />
</el-table>
</div>
</el-scrollbar>
</div>
</div>
<!-- </el-scrollbar> -->
<el-dialog v-model="dialogVisible" title="实训任务提交" width="565" custom-class="dialogClass" :show-close="false">
<el-dialog v-model="dialogVisible" title="实训任务提交" width="700" custom-class="dialogClass" :show-close="false">
<template #header="{ close, titleId, titleClass }">
<div class="my-header">
<span :id="titleId" :class="titleClass">实训任务提交</span>
@ -112,42 +144,33 @@
<img class="xtImg" src="../../../assets/images/线条.png" alt="" />
</template>
<div class="from-item">
<el-form :inline="true" label-position="right" label-width="84px" :model="form" class="demo-form-inline">
<el-form-item label="平均数:">
<el-input style="width: 120px" v-model="formInline.average" clearable />
<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" label-position="left">
<el-input style="width: 140px" v-model="formInline.max" clearable />
</el-form-item>
<el-form-item label="频次:" label-position="left" label-width="46px">
<el-input style="width: 140px" v-model="formInline.frequency" clearable />
</el-form-item>
</el-form-item>
<el-form-item label="众数:">
<el-input style="width: 120px" v-model="formInline.mode" clearable />
<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.text1" clearable />
</el-form-item>
<el-form-item>
<el-input style="width: 140px" v-model="formInline.text2" clearable />
</el-form-item>
</el-form-item>
<el-form-item label="中位数:">
<el-input style="width: 120px" v-model="formInline.median" clearable />
<el-form-item label="情感倾向分析: " label-width="120px">
<el-radio-group v-model="formInline.emotional" style="margin-left: 31px">
<el-radio value="1" label="正向" size="large"></el-radio>
<el-radio value="2" label="负向" size="large"></el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="标准差:">
<el-input style="width: 120px" v-model="formInline.standardDeviation" clearable />
</el-form-item>
<el-form-item label="方差:">
<el-input style="width: 120px" v-model="formInline.variance" clearable />
</el-form-item>
<el-form-item label="峰度:">
<el-input style="width: 120px" v-model="formInline.kurtosis" clearable />
</el-form-item>
<el-form-item label="标准误差:">
<el-input style="width: 120px" v-model="formInline.standardError" clearable />
</el-form-item>
<el-form-item label="偏度:">
<el-input style="width: 120px" v-model="formInline.skewness" clearable />
</el-form-item>
<el-form-item label="最大值:">
<el-input style="width: 120px" v-model="formInline.max" clearable />
</el-form-item>
<el-form-item label="最小值:">
<el-input style="width: 120px" v-model="formInline.min" clearable />
</el-form-item>
<el-form-item label="求和:">
<el-input style="width: 120px" v-model="formInline.summation" clearable />
</el-form-item>
<el-form-item label="观测数:">
<el-input style="width: 120px" v-model="formInline.observations" clearable />
<el-form-item label="词云生成: " label-width="120px">
<el-form-item label="中间最突出单词: " label-width="120px">
<el-input style="width: 140px" v-model="formInline.prominent" clearable />
</el-form-item>
</el-form-item>
</el-form>
</div>
@ -160,14 +183,21 @@
</el-dialog>
</template>
<script setup>
import { paginate } from "@/utils/index.js";
import * as echarts from "echarts";
import * as XLSX from "XLSX";
import "echarts-wordcloud/dist/echarts-wordcloud";
import "echarts-wordcloud/dist/echarts-wordcloud.min";
import * as portraitModel from "@/api/portraitModel";
import * as API from "@/api/AI.js";
import * as marketingAlgorithmApi from "@/api/marketing-algorithm.js";
import html2canvas from "html2canvas";
import useAlgorithmStore from "@/store/modules/algorithm.js";
import useUserStore from "@/store/modules/user";
import { getUserInfo } from "@/utils/auth";
const userInfo = JSON.parse(getUserInfo());
const loading = ref(false);
const loading2 = ref(false);
const { proxy } = getCurrentInstance();
const algorithmStore = useAlgorithmStore();
const multipleTableRef = ref(null);
@ -178,39 +208,42 @@ const n_dataTableQuery = ref({
tableName: "用户属性表",
userId: userInfo.userId,
});
const textType = ["酒店", "KTV", "丽人", "关食", "旅游", "健束", "教育", "商业", "房产", "汽车", "生活", "购物", "3C"];
const textType = [
{ name: "酒店", id: 1 },
{ name: "KTV", id: 2 },
{ name: "丽人", id: 3 },
{ name: "关食", id: 4 },
{ name: "旅游", id: 5 },
{ name: "健束", id: 6 },
{ name: "教育", id: 7 },
{ name: "商业", id: 8 },
{ name: "房产", id: 9 },
{ name: "汽车", id: 10 },
{ name: "生活", id: 11 },
{ name: "购物", id: 12 },
{ name: "3C", id: 13 },
];
const dialogVisible = ref(false);
const analysisData = ref([]);
const analysisHanderKry = ref([]);
//
const aWordFrequency=ref([])
//
const aWordFrequency = ref([]);
const s_commentType = ref("");
const tableLabel = reactive([
{ prop: "average", label: "平均数" },
{ prop: "median", label: "中位数" },
{ prop: "mode", label: "众数" },
{ prop: "standardDeviation", label: "标准差" },
{ prop: "variance", label: "方差" },
{ prop: "standardError", label: "标准误差" },
{ prop: "kurtosis", label: "峰度" },
{ prop: "skewness", label: "偏度" },
{ prop: "max", label: "最大值" },
{ prop: "min", label: "最小值" },
{ prop: "summation", label: "求和" },
{ prop: "observations", label: "观测数" },
{ prop: "max", label: "最多数量词语" },
{ prop: "frequency", label: "频次" },
{ prop: "text1", label: "前两位词语" },
{ prop: "text2", label: "前两位词语" },
{ prop: "emotional", label: "情感倾向分析" },
{ prop: "prominent", label: "中间最突出单词" },
]);
const formInline = ref({
average: "",
median: "",
mode: "",
standardDeviation: "",
variance: "",
standardError: "",
kurtosis: "",
skewness: "",
max: "",
min: "",
summation: "",
observations: "",
frequency: "",
text1: "",
text2: "",
emotional: "",
prominent: "",
});
const g_indicatorData = ref([]);
const preProcessText = ref({
@ -219,16 +252,29 @@ const preProcessText = ref({
text3: "",
});
const aOriginalDataOfAnalysisResults2 = ref({});
const nOriginalWordFrequency = ref([]); //
const nOriginalWordFrequencyNum = ref(0); //
const nOriginalWordFrequencySearch = ref([]); //
const mWordFrequency = ref({
index: 1,
size: 10,
namenum: "",
frequency: "",
}); //
//
const g_analyzeTheNumberOfDataItems = ref("");
//
const g_modelParameter = ref([]);
const n_emotiveTendency = ref(0);
const g_emotionAnalysis = ref(0);
const aCommentOpinion = ref([]);
//
const preProcess = (tetx) => {
if (analysisData.value.length == 0) {
if (g_indicatorData.value.length == 0) {
proxy.$modal.msgWarning("请先选择指标进行数据分析!");
preProcessText.value.text2 = "";
return;
}
API.dataPreprocessing({
mapList: analysisData.value,
@ -263,9 +309,11 @@ const handleSelectionChange = (type) => {
//
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 = res.data.map((item) => (item ? item.text : "")).join(",");
analysisData.value = res.data.filter((item) => item !== null);
loading.value = false;
proxy.$modal.msgSuccess("分析数据成功");
});
};
@ -279,8 +327,8 @@ const modelCalculation = () => {
proxy.$modal.msgWarning("请先分析数据/未选择模型参数!");
return;
}
const processedData = processArrayData(analysisHanderKry.value, analysisData.value);
marketingAlgorithmApi.getMarketingAlgorithmPreprocessing(JSON.stringify({ map: processedData, statistic: g_modelParameter.value, userId: n_dataTableQuery.value.userId })).then((res) => {
const processedData = processArrayData(["text"], analysisData.value);
marketingAlgorithmApi.getMarketingAlgorithmPreprocessing(JSON.stringify({ map: processedData, statistic: [preProcessText.value.text3 == "词云生成" ? "词频分析" : preProcessText.value.text3], userId: n_dataTableQuery.value.userId })).then((res) => {
aOriginalDataOfAnalysisResults2.value = res.data;
tableData.value = res.data.map((item) => item.statistics);
if (res.data.length > 5) {
@ -327,7 +375,7 @@ const submitTask = () => {
portraitModel
.submit({
userId: n_dataTableQuery.value.userId,
taskName: "描述性统计",
taskName: "情感分析",
numberOfErrors: 0,
})
.then((res) => {
@ -363,33 +411,198 @@ const restart = () => {
proxy.$modal.msgSuccess("重新开始成功");
multipleTableRef.value.clearSelection();
};
const captureElement = ref(null);
//
const download = () => {
aOriginalDataOfAnalysisResults2.value.forEach((item) => {
item.statistics.field = item.field;
for (let key in item.statistics) {
item.statistics[key] = item.statistics[key] ?? 0;
const download = async () => {
// let tableData = ["", ""];
// XLSX.utils.aoa_to_sheet(tableData);
if (preProcessText.value.text3 == "情感倾向分析" || preProcessText.value.text3 == "评论观点抽取") {
if (captureElement.value) {
try {
// 使 html2canvas
let VDOM = document.querySelector(".emotion_analysis_title");
let VDOM2 = document.querySelector(".result");
if (preProcessText.value.text3 == "情感倾向分析") {
VDOM.style.color = "#221f1f";
} else {
VDOM2.style.color = "#212020";
}
const canvas = await html2canvas(captureElement.value);
//
const image = canvas.toDataURL("image/png");
//
const link = document.createElement("a");
link.href = image;
link.download = `${preProcessText.value.text3}.png`; //
//
link.click();
if (preProcessText.value.text3 == "情感倾向分析") {
VDOM.style.color = "#ffffff";
} else {
VDOM2.style.color = "#ffffff";
}
} catch (error) {
console.error("无法生成图片", error);
}
}
} else if (preProcessText.value.text3 == "词频分析") {
const aoaData = [
["内容", "频次"], //
...nOriginalWordFrequency.value.map((item) => [item.keyword, item.frequency]), //
];
const worksheet = XLSX.utils.aoa_to_sheet(aoaData);
const workbook = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(workbook, worksheet, "Sheet1");
XLSX.writeFile(workbook, "词频分析.xlsx");
}
};
//
const sentimentAnalysis = () => {
let g_emotionAnalysisinfo = {};
if (g_indicatorData.value.length > 0) {
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;
marketingAlgorithmApi.getMarketingAlgorithmSentiment({ id: s_commentType.value, 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;
initChart();
} else if (preProcessText.value.text3 === "词频分析") {
nOriginalWordFrequency.value = res.data;
aWordFrequency.value = res.data.slice(0, 5);
nOriginalWordFrequencyNum.value = res.data.length;
} else if (preProcessText.value.text3 === "情感倾向分析") {
g_emotionAnalysisinfo = JSON.parse(res.data);
g_emotionAnalysis.value = JSON.parse(res.data)?.items[0]?.sentiment;
n_emotiveTendency.value = Math.round(g_emotionAnalysisinfo.items[0].positive_prob * 100);
} 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;
}, {});
}
loading.value = false;
proxy.$modal.msgSuccess("分析成功");
});
};
//
const clear = () => {
g_analyzeTheNumberOfDataItems.value = "";
aWordFrequency.value = [];
proxy.$modal.msgSuccess("清空成功");
};
const initChart = () => {
var myChart = echarts.init(document.getElementById("mywordcloud_positive"));
const arr = nOriginalWordFrequency.value.map((item) => {
return {
name: item.keyword,
value: item.frequency,
};
});
myChart.setOption({
title: {
text: "词云分析",
x: "center",
textStyle: {
fontSize: 23,
},
},
backgroundColor: "#ffffff",
tooltip: {
show: true,
},
toolbox: {
feature: {
saveAsImage: {
iconStyle: {
normal: {
color: "#FFFFFF",
},
},
},
},
},
marketingAlgorithmApi.getMarketingAlgorithmDownload(aOriginalDataOfAnalysisResults2.value).then((res) => {
const blob = new Blob([res], { type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" });
const url = window.URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = "描述性统计.xlsx";
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
window.URL.revokeObjectURL(url);
proxy.$modal.msgSuccess("下载成功");
series: [
{
name: "词云分析",
type: "wordCloud",
// //size: ['9%', '99%'],
sizeRange: [6, 66],
// //textRotation: [0, 45, 90, -45],
rotationRange: [-45, 90],
// //shape: 'circle',
// gridSize: 5,
// sizeRange: [12, 32],
width: "90%",
height: "86%",
textPadding: 0,
autoSize: {
enable: true,
minSize: 16,
},
textStyle: {
color: function () {
return "rgb(" + [Math.round(Math.random() * 160), Math.round(Math.random() * 160), Math.round(Math.random() * 160)].join(",") + ")";
},
emphasis: {
shadowBlur: 10,
shadowColor: "#333",
},
},
data: arr,
},
],
});
};
//
const sentimentAnalysis = () => {
marketingAlgorithmApi.getMarketingAlgorithmSentiment({ userId: n_dataTableQuery.value.userId, content: g_analyzeTheNumberOfDataItems.value, modelType: preProcessText.value.text3 }).then(res=>{
aWordFrequency.value=res.data
})
const commentType = (text) => {
s_commentType.value = text.id;
};
const wordFrequencyNext = () => {
if (mWordFrequency.value.frequency !== "" || mWordFrequency.value.namenum !== "") {
wordFrequencySearch();
} else {
aWordFrequency.value = paginate(nOriginalWordFrequency.value, mWordFrequency.value.index, mWordFrequency.value.size).data;
}
};
const wordFrequencySearch = () => {
//
loading2.value = true;
const filteredData = nOriginalWordFrequency.value.filter((item) => {
const matchesKeyword1 = mWordFrequency.value.frequency ? item.frequency === Number(mWordFrequency.value.frequency) : true;
const matchesKeyword2 = mWordFrequency.value.namenum ? item.keyword.length == mWordFrequency.value.namenum : true;
return matchesKeyword1 && matchesKeyword2;
});
aWordFrequency.value = filteredData.length > 5 ? paginate(filteredData, mWordFrequency.value.index, mWordFrequency.value.size).data : filteredData;
nOriginalWordFrequencyNum.value = filteredData.length;
setTimeout(() => {
loading2.value = false;
}, 600);
};
const switchingModels = () => {
//
n_emotiveTendency.value = 0;
aCommentOpinion.value = [];
nOriginalWordFrequencyNum.value = 0;
aWordFrequency.value = [];
nOriginalWordFrequency.value = [];
mWordFrequency.value.index = 1;
mWordFrequency.value.size = 5;
mWordFrequency.value.frequency = "";
mWordFrequency.value.namenum = "";
s_commentType.value = "";
};
</script>
@ -421,8 +634,6 @@ const sentimentAnalysis = () => {
}
}
.app-main {
// background-color: #f5f5f5;
min-height: 965px;
margin: 5px 20px 0;
height: 100%;
display: flex;
@ -430,7 +641,7 @@ const sentimentAnalysis = () => {
.main-left {
//
flex-direction: column;
min-height: 965px;
// min-height: 965px;
display: flex;
width: 205px;
height: 100%;
@ -476,9 +687,9 @@ const sentimentAnalysis = () => {
}
}
.main-right {
width: 1639px;
width: 100%;
// height: 100%;
padding: 20px;
// padding: 20px;
border: 1px solid #0452c6;
.text-type {
margin: 29px 0 20px 0px;
@ -489,16 +700,26 @@ const sentimentAnalysis = () => {
--el-button-bg-color: #041d3b;
--el-button-border-color: #1983dd;
}
.btnActive {
background: #409eff;
color: #ffffff;
}
}
.analysis {
.el-textarea {
margin-top: 10px;
:deep(.el-textarea) {
height: 343px;
background: #002652;
border-radius: 10px;
:deep(.el-textarea__inner) {
.el-textarea__inner {
min-height: 343px !important;
background: transparent;
box-shadow: 0 0 0 1px #1983dd;
box-shadow: 0 0 0 0px #1983dd !important;
border: 1px solid #1983dd;
color: #ffffff;
}
.el-input__count {
background: transparent !important;
color: #ffffff;
}
}
@ -530,6 +751,8 @@ const sentimentAnalysis = () => {
}
}
.analysisResults {
transition: all 6s;
.el-button {
width: 89px;
height: 31px;
@ -570,6 +793,109 @@ const sentimentAnalysis = () => {
margin-right: 55px;
}
}
.emotion_analysis {
position: relative;
display: flex;
// align-items: center;
justify-content: center;
gap: 30px;
color: #ffffff;
font-size: 14px;
height: 180px;
margin-top: 40px;
.emotion_analysis-ani-in-ri,
.emotion_analysis-ani-in-le {
display: flex;
align-items: center;
gap: 10px;
}
.emotion_analysis_title {
position: absolute;
top: 0px;
right: 48%;
font-size: 24px;
font-weight: normal;
}
:deep(.el-progress-bar__outer) {
background-color: #036fe2;
}
}
.comment-opinion {
padding: 30px 20px 0px 90px !important;
.result {
height: 40px;
-webkit-text-size-adjust: 100%;
font: 14px BlinkMacSystemFont, Roboto, Helvetica Neue, Helvetica, PingFangSC-Regular, Hiragino Sans GB, Microsoft YaHei, SimSun, sans-serif;
-webkit-tap-highlight-color: transparent;
-webkit-font-smoothing: antialiased;
font-family: -apple-system, BlinkMacSystemFont, SF Pro SC, SF Pro Text, Helvetica Neue, Helvetica, PingFang SC, Segoe UI, Roboto, Hiragino Sans GB, arial, microsoft yahei ui, Microsoft YaHei, SimSun, sans-serif;
font-weight: 400;
position: relative;
padding: 8px 0 8px 55px;
margin-right: 1px;
color: #ffffff;
.result-img {
-webkit-text-size-adjust: 100%;
font: 14px BlinkMacSystemFont, Roboto, Helvetica Neue, Helvetica, PingFangSC-Regular, Hiragino Sans GB, Microsoft YaHei, SimSun, sans-serif;
-webkit-tap-highlight-color: transparent;
-webkit-font-smoothing: antialiased;
font-family: -apple-system, BlinkMacSystemFont, SF Pro SC, SF Pro Text, Helvetica Neue, Helvetica, PingFang SC, Segoe UI, Roboto, Hiragino Sans GB, arial, microsoft yahei ui, Microsoft YaHei, SimSun, sans-serif;
font-weight: 400;
position: absolute;
top: 8px;
left: 0;
width: 26px;
height: 26px;
border-radius: 50%;
background-size: contain;
background-repeat: no-repeat;
background-image: url(../../../assets/images/笑脸.png);
background-color: #ff6b0f;
}
.result-neg {
position: absolute;
top: 8px;
left: 0;
width: 26px;
height: 26px;
border-radius: 50%;
background-size: contain;
background-repeat: no-repeat;
background-image: url(../../../assets/images/哭脸.png);
background-color: #60aefd;
}
.result-title {
line-height: 26px;
font-size: 14px;
}
.result-view {
position: relative;
display: inline-block;
padding: 0 10px;
margin-right: 2px;
line-height: 26px;
font-size: 14px;
top: -26px;
left: 61px;
.result-bar {
position: absolute;
top: 50%;
right: -1px;
transform: translateY(-50%);
height: 15px;
width: 1px;
color: #d8d8d8;
border-right: 1px solid #d8d8d8;
}
}
.result-view:last-child {
.result-bar {
border: none;
}
}
}
}
}
:deep(.el-form-item__label) {
color: #ffffff;
@ -590,4 +916,13 @@ p {
color: #ffffff !important;
font-size: 14px;
}
:deep(.pagination-container .el-pagination) {
//
position: static;
}
:deep(.demo-form-inline) {
.el-form-item__content {
flex-wrap: nowrap !important;
}
}
</style>

Loading…
Cancel
Save