增加预览视频组件并修复营销算法bug

dev-QQq
qinzhenpen 2 years ago
parent 598fb2f51f
commit df70da3a6b

@ -0,0 +1,82 @@
<template>
<div class="el-Aitools">
<div class="video-title">{{ videlinfo.resourcesName }}</div>
<video-player class="video-player" :options="playerOptions" :volume="0.6" @mounted="handleMounted" @ready="handleEvent($event)" @play="handleEvent($event)" @pause="handleEvent($event)" @ended="handleEvent($event)" @loadeddata="handleEvent($event)" @waiting="handleEvent($event)" @playing="handleEvent($event)" @canplay="handleEvent($event)" @canplaythrough="handleEvent($event)" @timeupdate="handleEvent(player?.currentTime())" />
</div>
</template>
<script setup name="video">
import cache from "@/plugins/cache";
import useAlgorithmStore from "@/store/modules/algorithm.js";
const algorithmStore = useAlgorithmStore();
import { VideoPlayer } from "@videojs-player/vue";
import "video.js/dist/video-js.css";
import { onMounted } from "vue";
const router = useRouter();
const player = shallowRef();
const videlinfo = ref({});
const videoSrc = ref("https://szjj.sztzjy.com:99/uploadFile/2024/2/26/3ef371decafa4bcc84c181dea4a0797f.mp4");
const playerOptions = ref({
playbackRates: [0.7, 1.0, 1.5, 2.0],
sources: [
{
type: "video/mp4",
src: videoSrc.value,
},
],
height: 600,
autoplay: "any",
muted: true,
loop: false,
preload: "auto",
language: "zh-CN",
playsinline: true,
notSupportedMessage: "此视频暂无法播放,请稍后再试",
controls: true,
muted: false, // false
controlBar: {
timeDivider: true,
durationDisplay: true,
remainingTimeDisplay: false,
fullscreenToggle: true,
},
});
const handleMounted = (payload) => {
player.value = payload.player;
// console.log("Basic player mounted", payload);
};
const handleEvent = (log) => {
// console.log("Basic player event", log);
};
onMounted(() => {
videlinfo.value = cache.session.getJSON("video_history")
videlinfo.value.resourcesName = videlinfo.value.resourcesName.replace(/.mp4/g, "")
});
</script>
<style scoped lang="scss">
.el-Aitools {
position: relative;
// padding: 20px 20px 0;
min-height: 100vh;
background: #020002;
.video-title{
color: #fff;
height: 50px;
padding: 10px;
font-size: 22px;
font-weight: normal;
}
.video-player {
position: absolute;
top: 50%;
left: 50%;
// width: 100%;
// height: 100%;
border: none;
transform: translate(-50%, -50%);
border-radius: 4px;
}
}
</style>

@ -140,7 +140,7 @@ export const dynamicRoutes = [
},
],
},
{
path: "",
component: Layout,
@ -180,6 +180,21 @@ export const dynamicRoutes = [
},
],
},
// 资源视频
{
path: "",
// component: Layout,
hidden: true,
redirect: "/video",
children: [
{
path: "/video",
component: () => import("@/components/video/index.vue"),
name: "video",
meta: { title: "视频中心", icon: "视频中心", affix: true },
},
],
},
];
const router = createRouter({

@ -2,7 +2,7 @@
* @Author: qinzhenpen qzp1807@126.com
* @Date: 2024-08-16 17:56:32
* @LastEditors: qinzhenpen qzp1807@126.com
* @LastEditTime: 2024-08-26 15:26:20
* @LastEditTime: 2024-08-28 14:59:50
* @FilePath: \digital-marketing\src\store\modules\algorithm.js
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
@ -16,7 +16,7 @@ const useAlgorithmStore = defineStore("algorithm", {
tableData: [],
tableKey:[],
userDataLabel:["用户属性表", "用户登录活跃表", "用户消费能力表", "用户行为表", "用户评论表"], //用户数据标签
userDataLabel2:["用户评论表"],
userDataLabel2:["用户商品评论数据"],
indexLibrary: [],
analysisData: [],
}),

@ -358,6 +358,9 @@ const task = () => {
if(formData.value1||formData.value4||formData.value5){
errorNumber=1
}
if(input.value!=="购物车数据"){
errorNumber=1
}
portraitModel
.submit({
userId: JSON.parse(getUserInfo()).userId,
@ -576,7 +579,6 @@ const computation = () => {
return;
}
if (input5.value && input6.value && input4.value) {
loading1.value = true;
const sendData = {
confidence: parseFloat(input5.value) / 100,
support: parseFloat(input6.value) / 100,
@ -585,6 +587,7 @@ const computation = () => {
};
API.associationRuleMining(sendData)
.then((res) => {
loading1.value = true;
uplodFlag.value = true;
tableData3.value = [];
tableLabel2.length = 0;
@ -616,6 +619,7 @@ const computation = () => {
});
} else {
proxy.$modal.msgWarning("请模型参数进行设置!");
loading1.value = false;
}
};
const upload = () => {
@ -640,6 +644,7 @@ const startOver = () => {
tableLabel.length = 0;
tableLabel2.length = 0;
uplodFlag.value = false;
loading1.value = false;
};
</script>

@ -92,6 +92,7 @@
</el-table>
<!-- <el-pagination style="margin-top:10px" background layout="prev, pager, next" :total="1000" /> -->
</div>
<div style="color:#FFFFFF;" v-show="showChart">{{iterations}}</div>
<div class="pdfRef" id="pdfRef" style="margin-top: 20px; gap: 25px; display: flex" v-show="showChart">
<!-- <img src="../../../assets/images/图1.png" alt=""> -->
<div style="background: #ffffff">
@ -310,11 +311,14 @@ const task = () => {
return;
}
}
if (formInline2.value1 !== "3") {
errorNumber = 1;
if(parseFloat(formInline2.value1)!==parseFloat(input5.value)){
errorNumber=1
}
if (formInline2.value2 !== input6.value) {
errorNumber = 1;
if(parseFloat(formInline2.value2)!==parseFloat(iterations.value)){
errorNumber=1
}
if(input.value!=="客户细分数据表"){
errorNumber=1
}
portraitModel
.submit({
@ -544,6 +548,7 @@ const optionData2 = () => {
};
const showChart = ref(false);
//
const iterations=ref(0)
const nowData = ref([]);
const clusterAnalysisCalculation = () => {
if (tableData2.value.length === 0 || input2.value == "" || input3.value == "") {
@ -563,8 +568,8 @@ const clusterAnalysisCalculation = () => {
showChart.value = true;
let sex = 1;
tableData3.value = [];
nowData.value = res.data;
res.data.forEach((item, index) => {
nowData.value = res.data.clusters;
res.data.clusters.forEach((item, index) => {
const newItem = {};
tableLabel.forEach((label, index) => {
if (index === 0) {
@ -577,6 +582,7 @@ const clusterAnalysisCalculation = () => {
sex++;
tableData3.value.push(newItem);
tableData3.value[index].children = [];
iterations.value=res.data.iterations
const children = ref([]);
item.forEach((item2, sexx) => {
const newItem2 = {};

@ -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">使用客户细分数据消费得分Spending Score指标进行描述性统计分析并提交实训任务</p>
<p style="font-weight: 400; font-size: 15px; color: #e2e7ee !important">使用客户细分数据消费得分Spending Score指标进行描述性统计分析并提交实训任务</p>
</div>
<div class="main-but">
<el-button @click="knowledgeImport">
@ -93,7 +93,7 @@
</el-scrollbar>
</div>
</div>
<el-dialog v-model="dialogVisible" title="实训任务提交" width="565" custom-class="dialogClass" :show-close="false">
<el-dialog v-model="dialogVisible" title="实训任务提交" width="565" custom-class="dialogClass" :show-close="false" @close="closeDialog">
<template #header="{ close, titleId, titleClass }">
<div class="my-header">
<span :id="titleId" :class="titleClass">实训任务提交</span>
@ -254,13 +254,13 @@ const b_introductionOfAlgorithmKnowledge = ref(false);
const runResultShow = ref(false);
const n_dataTableQuery = ref({
index: 1,
size: 5,
size: 10,
tableName: algorithmStore.userDataLabel[0],
userId: userInfo.userId,
});
const gAnalysisResults = ref({
index: 1,
size: 5,
size: 10,
});
const dialogVisible = ref(false);
//
@ -409,7 +409,7 @@ const submit = () => {
if (res.data.length > 5) {
n_analyzeTheNumberOfDataItems.value = res.data.length;
aAnalyzeTheRawData.value = res.data;
analysisData.value = res.data.slice(0, 5);
analysisData.value = res.data.slice(0, 10);
}
proxy.$modal.msgSuccess("分析数据成功");
});
@ -481,7 +481,7 @@ const submitTask = () => {
if (Number(formInline.value[key]) != g_taskAnswer.value[key]) {
const label = tableLabel.find((item) => item.prop == key);
flat.value = true;
proxy.$modal.msgWarning(`${label.label}错误`);
// proxy.$modal.msgWarning(`${label.label}`);
}
}
}
@ -493,7 +493,11 @@ const submitTask = () => {
})
.then((res) => {
dialogVisible.value = false;
flat.value = false;
proxy.$modal.msgSuccess("提交成功");
})
.catch((err) => {
flat.value = false;
});
};
//
@ -533,6 +537,7 @@ const updatePageAnalysisResults = () => {
};
//
const download = () => {
if (tableData.value.length == 0) return proxy.$modal.msgWarning("请先计算数据!");
aOriginalDataOfAnalysisResults2.value.forEach((item) => {
item.statistics.field = item.field;
for (let key in item.statistics) {
@ -553,6 +558,13 @@ const download = () => {
proxy.$modal.msgSuccess("下载成功");
});
};
const closeDialog=()=>{
dialogVisible.value = false;
flat.value = false
for (let key in formInline.value) {
formInline.value[key] = "";
}
}
</script>
<style lang="scss" scoped>

@ -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">使用用户商品评论数据进行各类文本挖掘任务分析评论情感情绪最后提交实训任务</p>
<p style="font-weight: 400; font-size: 15px; color: #e2e7ee !important">使用用户商品评论数据进行各类文本挖掘任务分析评论情感情绪最后提交实训任务</p>
</div>
<div class="main-but">
<el-button @click="knowledgeImport">
@ -69,7 +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 v-model="g_analyzeTheNumberOfDataItems" :rows="2" type="textarea" placeholder="" />
</div>
@ -120,7 +122,7 @@
<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 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>
@ -133,12 +135,22 @@
<div class="result-bar"></div>
</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-scrollbar>
</div>
</div>
<el-dialog v-model="dialogVisible" title="实训任务提交" width="700" custom-class="dialogClass" :show-close="false">
<el-dialog v-model="dialogVisible" title="实训任务提交" width="700" custom-class="dialogClass" :show-close="false" @close="closeDialog">
<template #header="{ close, titleId, titleClass }">
<div class="my-header">
<span :id="titleId" :class="titleClass">实训任务提交</span>
@ -503,13 +515,14 @@ const downloadStatus = ref(false);
//
const flat = ref(false);
const g_submitVerification = ref({
max: "13",
frequency: "3",
text1: "质量",
text2: "包装好",
max: "安装",
frequency: "6",
text1: "",
text2: "",
emotional: "负向",
prominent: "",
prominent: "安装",
});
const s_commentType = ref("");
//
const preProcess = (tetx) => {
if (g_indicatorData.value.length == 0) {
@ -598,9 +611,15 @@ const submitTask = () => {
return;
} else {
if (formInline.value[key] != g_submitVerification.value[key]) {
const label = tableLabel.find((item) => item.prop == key);
proxy.$modal.msgWarning(`${label.label}错误`);
flat.value = true;
// text1text2,
if (key == "text1" || key == "text2") {
const validTexts = ["text1", "text2"];
if (validTexts.includes(key) && !["包装好", "好评少"].includes(formInline.value[key])) {
flat.value = true;
}
} else {
flat.value = true;
}
}
}
}
@ -648,6 +667,8 @@ const restart = () => {
nOriginalWordFrequencyNum.value = 0;
aWordFrequency.value = [];
nOriginalWordFrequency.value = [];
s_commentType.value = "";
aCommentOpinion.value = "";
proxy.$modal.msgSuccess("重新开始!");
multipleTableRef.value.clearSelection();
};
@ -709,7 +730,9 @@ 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 === "情感倾向分析") {
@ -740,7 +763,7 @@ const sentimentAnalysis = () => {
.catch((err) => {
loading.value = false;
});
} else if (preProcessText.value.text3 !== "评论观点抽取") {
} else if (preProcessText.value.text3 !== "情感倾向分析") {
marketingAlgorithmApi
.getMarketingAlgorithmSentiment({ userId: n_dataTableQuery.value.userId, content: g_analyzeTheNumberOfDataItems.value, modelType: preProcessText.value.text3 == "词云生成" ? "词频分析" : preProcessText.value.text3 })
.then((res) => {
@ -751,33 +774,18 @@ 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("分析成功");
})
@ -785,6 +793,25 @@ const sentimentAnalysis = () => {
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("");
// })
// .catch((err) => {
// loading.value = false;
// });
// }
};
//
const clear = () => {
@ -793,6 +820,8 @@ const clear = () => {
aWordFrequency.value = [];
loading.value = false;
downloadStatus.value = false;
aCommentOpinion.value = [];
s_commentType.value = "";
proxy.$modal.msgSuccess("清空成功");
};
const initChart = () => {
@ -809,6 +838,8 @@ const initChart = () => {
x: "center",
textStyle: {
fontSize: 23,
color: "#000000",
},
},
backgroundColor: "#ffffff",
@ -826,24 +857,24 @@ const initChart = () => {
},
},
},
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,
size: ["9%", "99%"],
sizeRange: [33, 80], //
textRotation: [0, 45, 90, -45],
rotationRange: [-90, 90], //
shape: "circle",
gridSize: 5, //
sizeRange: [33, 80], //
width: "100%", //
height: "100%", //
textPadding: 10, //
autoSize: {
enable: true,
minSize: 16,
minSize: 33, //
maxSize: 80, //
},
textStyle: {
color: function () {
@ -859,7 +890,6 @@ const initChart = () => {
],
});
};
const wordFrequencyNext = () => {
if (mWordFrequency.value.frequency !== "" || mWordFrequency.value.namenum !== "") {
wordFrequencySearch();
@ -892,7 +922,18 @@ const switchingModels = () => {
mWordFrequency.value.size = 5;
mWordFrequency.value.frequency = "";
mWordFrequency.value.namenum = "";
s_commentType.value = "";
};
const commentType = (text) => {
s_commentType.value = text.id;
};
const closeDialog=()=>{
dialogVisible.value = false;
flat.value = false
for (let key in formInline.value) {
formInline.value[key] = "";
}
}
</script>
<style lang="scss" scoped>

@ -148,7 +148,7 @@
<div class="from-item">
<el-form :inline="true" label-position="right" label-width="50px" :model="form" class="demo-form-inline">
<el-form-item label="x">
<el-input style="width: 225px" v-model="formInline2.user" clearable placeholder="请输入x 多个以英文逗号隔开" />
<el-input style="width: 225px" v-model="formInline2.user" clearable placeholder="请输入x" />
</el-form-item>
</el-form>
</div>
@ -353,8 +353,11 @@ const task = () => {
if (parseFloat(formInline3.value3) !== parseFloat(predictionResults.value)) {
errorNumber = 1;
}
} else {
errorNumber = 1;
if(input.value!=="销售预测数据"){
errorNumber=1
}
}else{
errorNumber=1
}
portraitModel
.submit({

@ -11,7 +11,7 @@
</a>
</div>
<div class="el_bon">
<a target="_blank" @click="showResource(i.resourcesUrl)">
<a target="_blank" @click="showResource(i)">
<img data-src="https://jrdsj.sztzjy.com:598/assets/%E5%AD%A6%E4%B9%A0%E8%B5%84%E6%BA%90-1.a6a80357.png" :src="getImg(i.resourcesImg)" />
</a>
</div>
@ -22,11 +22,12 @@
</el-scrollbar>
</div>
</template>
<script setup>
<script setup name="learningResources">
import cache from "@/plugins/cache";
import * as API from "@/api/prtrait/prtrait.js";
import { getAssetsFile } from "@/utils";
import { getUserInfo } from "@/utils/auth";
import { computed, onMounted } from "vue";
const getImg = (i) => {
return getAssetsFile(i);
};
@ -50,42 +51,41 @@ onMounted(() => {
});
const showResource = async (i) => {
window.open("/video", "_blank");
cache.session.set('video_history',JSON.stringify(i))
// const newWindow=window.open(`http://192.168.2.4:8800/api/stu/concept/block/getResource?`+`module=${data2.module}`+`&name=${i}`)
// window.open(`http://qkljr.sztzjy.com:90/api/stu/concept/block/getResource?`+`module=${data2.module}`+`&name=${i}`)
if (i.includes("mp4")) {
const newWindow = window.open("", "_blank");
newWindow.document.write(`
<html>
<head>
<title>视频播放</title>
<style>
body {
margin: 0;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
background-color: #333333;
}
video {
width: 90%;
// max-width: 800px;
}
</style>
</head>
<body>
<video controls autoplay controlsList="nodownload">
<source src="http://118.31.7.2:8042/file/${i}" type="video/mp4">
</video>
</body>
</html>
`);
}
if (i.includes("pdf")) {
// window.open(`http://qkljr.sztzjy.com:90/api/stu/concept/block/getResource?`+`module=${data2.module}`+`&name=${i}#toolbar=0`)
window.open(`http://118.31.7.2:8042/file/${i}#toolbar=0`);
// window.open(`http://202.199.90.115:8800/api/stu/concept/block/getResource?`+`module=${data2.module}`+`&name=${i}`)
}
// if (i.includes("mp4")) {
// const newWindow = window.open("", "_blank");
// newWindow.document.write(`
// <html>
// <head>
// <title></title>
// <style>
// // body {
// // margin: 0;
// // display: flex;
// // justify-content: center;
// // align-items: center;
// // height: 100vh;
// // background-color: #333333;
// // }
// </style>
// </head>
// <body>
// // <video controls autoplay controlsList="nodownload">
// // <source src="http://118.31.7.2:8042/file/${i}" type="video/mp4">
// // </video>
// </body>
// </html>
// `);
// }
// if (i.includes("pdf")) {
// // window.open(`http://qkljr.sztzjy.com:90/api/stu/concept/block/getResource?`+`module=${data2.module}`+`&name=${i}#toolbar=0`)
// window.open(`http://118.31.7.2:8042/file/${i}#toolbar=0`);
// // window.open(`http://202.199.90.115:8800/api/stu/concept/block/getResource?`+`module=${data2.module}`+`&name=${i}`)
// }
};
const timer = ref(null);
let seconds = 0;

Loading…
Cancel
Save