dev-QQq
qinzhenpen 2 years ago
parent eb7d300d54
commit 25b8c2a2a3

@ -2,4 +2,4 @@
{
"htmlWhitespaceSensitivity": "ignore",
"printWidth": 1000
}
}

Binary file not shown.

@ -2,7 +2,7 @@
* @Author: qinzhenpen qzp1807@126.com
* @Date: 2024-08-16 10:14:59
* @LastEditors: qinzhenpen qzp1807@126.com
* @LastEditTime: 2024-08-19 15:07:27
* @LastEditTime: 2024-08-22 11:40:05
* @FilePath: \vue3\src\api\marketing-algorithm.js
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
@ -72,4 +72,12 @@ export function getMarketingAlgorithmSentiment(data) {
method: "POST",
data,
});
}
}
// 情感倾向分析
export function getMarketingAlgorithmSentimentAnalysis(data) {
return request({
url: "/api/python/sentimentAnaly",
method: "POST",
data,
});
}

@ -7,6 +7,14 @@ export function getUserTableData(data) {
params: data,
});
}
// 查询用户数据基本信息
export function getUserTableInfo(params) {
return request({
url: "/api/userprofile/getBaseInfo",
method: "get",
params,
});
}
//数据下载-RFM分析
export function downloadDataByRFM(data) {
return request({

@ -135,7 +135,10 @@ aside {
.pagination-container {
margin-top: 30px;
background-color: transparent !important;
.el-pagination__total,.el-pagination__goto,.el-pagination__classifier{
.el-pagination__total,
.el-pagination__goto,
.el-pagination__classifier {
color: #ffffff !important;
}
}
@ -211,7 +214,8 @@ aside {
.el-button--large.is-round {
padding: 12px 20px 12px 40px !important;
}
.el-button{
.el-button {
width: 89px;
height: 31px;
padding: 12px 20px 12px 40px !important;
@ -223,36 +227,43 @@ aside {
.app-container2 {
margin: 10px;
box-shadow: 0px 0px 13px 0px #0452C6;
border-radius: 10px;
padding: 25px 25px 10px 25px;
// box-shadow: 0px 0px 13px 0px #0452C6;
border-radius: 10px;
// padding: 25px 25px 10px 25px;
}
.dialogClass{
background:url('@/assets/images/弹框.png') !important;
.dialogClass {
background: url('@/assets/images/弹框.png') !important;
background-size: 100% 100% !important;
.el-dialog__header{
padding: 5px 0px;
margin-right: 5px !important;
.gbImg{
cursor: pointer;
width: 51px;
height: 31px;
background-size: 100% 100%;
}
.el-dialog__header {
padding: 5px 0px;
margin-right: 5px !important;
.gbImg {
cursor: pointer;
width: 51px;
height: 31px;
background-size: 100% 100%;
}
}
.xtImg {
margin-left: 18px;
width: 530px;
}
.xtImg{
margin-left: 18px;
width: 530px;
}
}
.my-header {
display: flex;
flex-direction: row;
justify-content: space-between;
gap: 16px;
text-align: center;
span{
color: #FFFFFF;
padding: 38px 20px 0;
display: flex;
flex-direction: row;
justify-content: space-between;
gap: 16px;
text-align: center;
span {
color: #FFFFFF;
padding: 38px 20px 0;
}
}
}

@ -8,6 +8,7 @@ const useAlgorithmStore = defineStore("algorithm", {
tableData: [],
tableKey:[],
userDataLabel:["用户属性表", "用户登录活跃表", "用户消费能力表", "用户行为表", "用户评论表"], //用户数据标签
userDataLabel2:["用户属性表", "用户登录活跃表", "用户消费能力表", "用户行为表", "用户评论表"],
indexLibrary: [],
analysisData: [],
}),

@ -1,95 +1,102 @@
import axios from 'axios'
import { ElNotification , ElMessageBox, ElMessage, ElLoading } from 'element-plus'
import { getToken } from '@/utils/auth'
import errorCode from '@/utils/errorCode'
import { tansParams, blobValidate } from '@/utils/ruoyi'
import cache from '@/plugins/cache'
import { saveAs } from 'file-saver'
import useUserStore from '@/store/modules/user'
import axios from "axios";
import { ElNotification, ElMessageBox, ElMessage, ElLoading } from "element-plus";
import { getToken } from "@/utils/auth";
import errorCode from "@/utils/errorCode";
import { tansParams, blobValidate } from "@/utils/ruoyi";
import cache from "@/plugins/cache";
import { saveAs } from "file-saver";
import useUserStore from "@/store/modules/user";
let downloadLoadingInstance;
// 是否显示重新登录
export let isRelogin = { show: false };
axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'
axios.defaults.headers["Content-Type"] = "application/json;charset=utf-8";
// 创建axios实例
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.4:9868/",
// 超时
timeout: 100000
})
timeout: 100000,
});
// request拦截器
service.interceptors.request.use(config => {
// 是否需要设置 token
const isToken = (config.headers || {}).isToken === false
// 是否需要防止数据重复提交
const isRepeatSubmit = (config.headers || {}).repeatSubmit === false
if (getToken() && !isToken) {
config.headers['Authorization'] = 'Bearer ' + getToken() // 让每个请求携带自定义token 请根据实际情况自行修改
}
// get请求映射params参数
if (config.method === 'get' && config.params) {
let url = config.url + '?' + tansParams(config.params);
url = url.slice(0, -1);
config.params = {};
config.url = url;
}
if (!isRepeatSubmit && (config.method === 'post' || config.method === 'put')) {
const requestObj = {
url: config.url,
data: typeof config.data === 'object' ? JSON.stringify(config.data) : config.data,
time: new Date().getTime()
service.interceptors.request.use(
(config) => {
// 是否需要设置 token
const isToken = (config.headers || {}).isToken === false;
// 是否需要防止数据重复提交
const isRepeatSubmit = (config.headers || {}).repeatSubmit === false;
if (getToken() && !isToken) {
config.headers["Authorization"] = "Bearer " + getToken(); // 让每个请求携带自定义token 请根据实际情况自行修改
}
// get请求映射params参数
if (config.method === "get" && config.params) {
let url = config.url + "?" + tansParams(config.params);
url = url.slice(0, -1);
config.params = {};
config.url = url;
}
const sessionObj = cache.session.getJSON('sessionObj')
if (!isRepeatSubmit && (config.method === "post" || config.method === "put")) {
const requestObj = {
url: config.url,
data: typeof config.data === "object" ? JSON.stringify(config.data) : config.data,
time: new Date().getTime(),
};
const sessionObj = cache.session.getJSON("sessionObj");
}
return config;
},
(error) => {
console.log(error);
Promise.reject(error);
}
return config
}, error => {
console.log(error)
Promise.reject(error)
})
);
// 响应拦截器
service.interceptors.response.use(res => {
service.interceptors.response.use(
(res) => {
// 未设置状态码则默认成功状态
const code = res.data.code || 200;
// console.log(code);
// 获取错误信息
const msg = errorCode[code] || res.data.msg || errorCode['default']
const msg = errorCode[code] || res.data.msg || errorCode["default"];
// 二进制数据则直接返回
if (res.request.responseType === 'blob' || res.request.responseType === 'arraybuffer') {
return res.data
if (res.request.responseType === "blob" || res.request.responseType === "arraybuffer") {
return res.data;
}
if (code === 401) {
if (!isRelogin.show) {
isRelogin.show = true;
ElMessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', { confirmButtonText: '重新登录', cancelButtonText: '取消', type: 'warning' }).then(() => {
isRelogin.show = false;
useUserStore().logOut().then(() => {
location.href = '/index';
ElMessageBox.confirm("登录状态已过期,您可以继续留在该页面,或者重新登录", "系统提示", { confirmButtonText: "重新登录", cancelButtonText: "取消", type: "warning" })
.then(() => {
isRelogin.show = false;
useUserStore()
.logOut()
.then(() => {
location.href = "/index";
});
})
}).catch(() => {
isRelogin.show = false;
});
}
return Promise.reject('无效的会话,或者会话已过期,请重新登录。')
.catch(() => {
isRelogin.show = false;
});
}
return Promise.reject("无效的会话,或者会话已过期,请重新登录。");
} else if (code === 500) {
ElMessage({ message: msg, type: 'error' })
return Promise.reject(new Error(msg))
ElMessage({ message: msg, type: "error" });
return Promise.reject(new Error(msg));
} else if (code === 601) {
ElMessage({ message: msg, type: 'warning' })
return Promise.reject(new Error(msg))
ElMessage({ message: msg, type: "warning" });
return Promise.reject(new Error(msg));
} else if (code !== 200) {
ElNotification.error({ title: msg })
return Promise.reject('error')
ElNotification.error({ title: msg });
return Promise.reject("error");
} else {
return Promise.resolve(res.data)
return Promise.resolve(res.data);
}
},
error => {
console.log('err' + error)
(error) => {
console.log("err" + error);
let { message } = error;
if (message == "Network Error") {
message = "后端接口连接异常";
@ -97,50 +104,61 @@ service.interceptors.response.use(res => {
message = "系统接口请求超时";
} else if (message.includes("Request failed with status code")) {
if (message.includes("401")) {
ElMessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', { confirmButtonText: '重新登录', cancelButtonText: '取消', type: 'warning' }).then(() => {
isRelogin.show = true;
useUserStore().logOut().then(() => {
location.href = '/login';
ElMessageBox.confirm("登录状态已过期,您可以继续留在该页面,或者重新登录", "系统提示", { confirmButtonText: "重新登录", cancelButtonText: "取消", type: "warning" })
.then(() => {
isRelogin.show = true;
useUserStore()
.logOut()
.then(() => {
location.href = "/login";
});
})
}).catch(() => {
isRelogin.show = false;
});
.catch(() => {
isRelogin.show = false;
});
} else if (message.includes("code 400")) {
// ElNotification.error({ title: error.response.data })
ElMessage({ message: error.response.data.msg, type: 'error' })
ElMessage({ message: error.response.data.msg, type: "error" });
}
message = "系统接口" + message.substr(message.length - 3) + "异常";
}
// ElMessage({ message: message, type: 'error', duration: 5 * 1000 })
return Promise.reject(error)
return Promise.reject(error);
}
)
);
// 通用下载方法
export function download(url, params, filename, config) {
downloadLoadingInstance = ElLoading.service({ text: "正在下载数据,请稍候", background: "rgba(0, 0, 0, 0.7)", })
return service.post(url, params, {
transformRequest: [(params) => { return tansParams(params) }],
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
responseType: 'blob',
...config
}).then(async (data) => {
const isBlob = blobValidate(data);
if (isBlob) {
const blob = new Blob([data])
saveAs(blob, filename)
} else {
const resText = await data.text();
const rspObj = JSON.parse(resText);
const errMsg = errorCode[rspObj.code] || rspObj.msg || errorCode['default']
ElMessage.error(errMsg);
}
downloadLoadingInstance.close();
}).catch((r) => {
console.error(r)
ElMessage.error('下载文件出现错误,请联系管理员!')
downloadLoadingInstance.close();
})
downloadLoadingInstance = ElLoading.service({ text: "正在下载数据,请稍候", background: "rgba(0, 0, 0, 0.7)" });
return service
.post(url, params, {
transformRequest: [
(params) => {
return tansParams(params);
},
],
headers: { "Content-Type": "application/x-www-form-urlencoded" },
responseType: "blob",
...config,
})
.then(async (data) => {
const isBlob = blobValidate(data);
if (isBlob) {
const blob = new Blob([data]);
saveAs(blob, filename);
} else {
const resText = await data.text();
const rspObj = JSON.parse(resText);
const errMsg = errorCode[rspObj.code] || rspObj.msg || errorCode["default"];
ElMessage.error(errMsg);
}
downloadLoadingInstance.close();
})
.catch((r) => {
console.error(r);
ElMessage.error("下载文件出现错误,请联系管理员!");
downloadLoadingInstance.close();
});
}
export default service
export default service;

@ -1,20 +1,7 @@
<template>
<div>
<el-dialog
:title="title"
style="width: 1308px; height: 838px"
custom-class="dialog"
v-model="props.showModel"
:before-close="close"
>
<div
class="diaMain"
style="
margin-top: -35px;
padding: 10px;
padding-left: 20px;
"
>
<el-dialog :title="title" style="width: 1308px; height: 838px" custom-class="dialog" v-model="props.showModel" :before-close="close">
<div class="diaMain" style="margin-top: -35px; padding: 10px; padding-left: 20px">
<el-scrollbar height="730px">
<slot name="content" class="main"></slot>
</el-scrollbar>
@ -61,15 +48,12 @@ const submit = () => {
};
</script>
<style lang="scss" scoped>
</style>
<style lang="scss">
.diaMain{
img{
.diaMain {
img {
max-height: 1200px;
max-width: 1200px;
}
p{
p {
font-size: 15px;
}
}
@ -102,11 +86,14 @@ const submit = () => {
.el-dialog__footer {
text-align: center;
}
.tj{
color: #FFFFFF;
}
.cxks{
background: url('@/assets/images/szjj/重新开始.png') no-repeat;
}
.tj {
color: #ffffff;
}
.cxks {
background: url("@/assets/images/szjj/重新开始.png") no-repeat;
}
}
p {
// color: #1d2528 !important;
}
</style>

@ -2,12 +2,12 @@
* @Author: qinzhenpen qzp1807@126.com
* @Date: 2024-08-20 17:50:08
* @LastEditors: qinzhenpen qzp1807@126.com
* @LastEditTime: 2024-08-21 17:25:35
* @LastEditTime: 2024-08-22 17:12:34
* @FilePath: \vue3\src\views\digitalMarketTech\index.vue
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
-->
<template>
<div class="rgzn_top app-container2">
<div class="rgzn_top app-container">
<div class="top_item">
<el-button :class="{ active: isActive === 1 }" @click="activeIndex(1)">
<img src="@/assets/images/大数据.png" />

@ -2,7 +2,7 @@
<!-- <el-scrollbar ref="scrollbar" height="800px"> -->
<div class="main-top">
<span style="font-weight: bold; font-size: 18px; color: #3596eb">任务描述</span>
<p style="font-weight: 400; font-size: 12px; color: #e6e6e6">给出任务清单参考做哪些数据的统计分析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">给出任务清单参考做哪些数据的统计分析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>
</div>
<div class="main-but">
<el-button @click="runResultShow = true">

@ -60,7 +60,7 @@ const n_dataTableQuery = ref({
});
const datatotal = ref(0);
const nzIndex = ref(0);
const nzData = ["用户属性表", "用户登录活跃表", "用户消费能力表", "用户行为表", "用户评论表"];
const nzData = ref([]);
const zjIndex = ref(-1);
const zjData = ref([]);
const tableLabel = ref([
@ -77,6 +77,7 @@ const tableLabel = ref([
{ prop: "updateTime", label: "注册时间" },
{ prop: "location", label: "所在地" },
]);
const tableLabel2 = ref([]);
const arrhander = ref([]);
const arrhanderkey = ref([]);
@ -119,28 +120,31 @@ const selectType = (type) => {
};
const getSurface = () => {
loading.value = true;
portraitModel.getUserTableData(n_dataTableQuery.value).then((res) => {
tableData.value = res?.data?.list
datatotal.value = res?.data?.total
tableLabel2.value = [];
if (tableData.value[0]?.stepOneA) {
arrhander.value = JSON.parse(tableData.value[0].stepOneA);
arrhanderkey.value = Object.keys(tableData.value[0]).slice(2, arrhander.value.length + 2);
arrhander.value.forEach((item, index) => {
tableLabel2.value.push({
prop: arrhanderkey.value[index],
label: item,
portraitModel
.getUserTableData(n_dataTableQuery.value)
.then((res) => {
tableData.value = res?.data?.list;
datatotal.value = res?.data?.total;
tableLabel2.value = [];
if (tableData.value[0]?.stepOneA) {
arrhander.value = JSON.parse(tableData.value[0].stepOneA);
arrhanderkey.value = Object.keys(tableData.value[0]).slice(2, arrhander.value.length + 2);
arrhander.value.forEach((item, index) => {
tableLabel2.value.push({
prop: arrhanderkey.value[index],
label: item,
});
});
});
tableLabel.value = tableLabel2.value;
}
setTimeout(()=>{
tableLabel.value = tableLabel2.value;
}
setTimeout(() => {
loading.value = false;
}, 1000);
})
.catch((err) => {
loading.value = false;
},1000)
}).catch(err=>{
loading.value = false;
tableData.value=[]
})
tableData.value = [];
});
};
//
const importData = (e) => {
@ -157,7 +161,10 @@ const importData = (e) => {
};
//
const selectZJ = (item) => {
marketingAlgorithmApi.getMarketingAlgorithmTable();
portraitModel.getUserTableInfo({ userId: userInfo.userId }).then((res) => {
nzData.value = res.data.tableNames;
algorithmStore.userDataLabel = [...res?.data.tableNames, ...res.data.selfBuiltTable];
});
};
//
const getZJData = () => {
@ -166,6 +173,7 @@ const getZJData = () => {
});
};
onMounted(() => {
selectZJ();
getSurface();
getZJData();
});

@ -273,7 +273,6 @@
<script setup>
import * as portraitModel from "@/api/portraitModel";
import popModel from "@/views/components/popModal.vue";
import { htmlPdf } from "@/utils/pdf.js";
import * as echarts from "echarts";
@ -296,8 +295,8 @@ const formInline2 = reactive({
value6: "",
});
const task = () => {
for(let key in formInline2){
if(formInline2[key] == ""){
for (let key in formInline2) {
if (formInline2[key] == "") {
proxy.$modal.msgError("请填写完整!");
return;
}
@ -312,7 +311,6 @@ const task = () => {
dialogVisible.value = false;
proxy.$modal.msgSuccess("提交成功");
});
};
const algorithmicKnowledge = () => {
runResultShow.value = true;
@ -513,148 +511,147 @@ const optionData2 = () => {
proxy.$modal.msgSuccess("预处理成功!");
});
}
}
const showChart = ref(false);
//
const nowData = ref([]);
const clusterAnalysisCalculation = () => {
if (tableData2.value.length === 0 || input2.value == "" || input3.value == "") {
proxy.$modal.msgWarning("请先计算/对数据进行预处理!");
return;
}
if (input5.value && input6.value && input4.value) {
const sendData = {
k: input5.value,
t: input6.value,
userId: JSON.parse(getUserInfo()).userId,
deduplicatedDataList: resTable2.value,
};
API.clusterAnalysisPlot(sendData)
.then((res) => {
showChart.value = true;
let sex = 1;
tableData3.value = [];
nowData.value = res.data;
res.data.forEach((item, index) => {
const newItem = {};
tableLabel.forEach((label, index) => {
if (index === 0) {
newItem[label.prop] = "簇" + sex; //
} else {
newItem[label.prop] = "";
}
});
newItem["TSuid"] = sex;
sex++;
tableData3.value.push(newItem);
tableData3.value[index].children = [];
const children = ref([]);
item.forEach((item2, sexx) => {
const newItem2 = {};
tableLabel.forEach((label, index2) => {
newItem2[label.prop] = item2[index2]; //
});
newItem2["TSuid"] = "" + sex + sexx;
children.value.push(newItem2);
});
tableData3.value[index].children = children.value;
console.log(tableData3.value);
};
const showChart = ref(false);
//
const nowData = ref([]);
const clusterAnalysisCalculation = () => {
if (tableData2.value.length === 0 || input2.value == "" || input3.value == "") {
proxy.$modal.msgWarning("请先计算/对数据进行预处理!");
return;
}
if (input5.value && input6.value && input4.value) {
const sendData = {
k: input5.value,
t: input6.value,
userId: JSON.parse(getUserInfo()).userId,
deduplicatedDataList: resTable2.value,
};
API.clusterAnalysisPlot(sendData)
.then((res) => {
showChart.value = true;
let sex = 1;
tableData3.value = [];
nowData.value = res.data;
res.data.forEach((item, index) => {
const newItem = {};
tableLabel.forEach((label, index) => {
if (index === 0) {
newItem[label.prop] = "簇" + sex; //
} else {
newItem[label.prop] = "";
}
});
})
.then(() => {
API.clusterAnalysis(sendData).then((res) => {
myChart.setOption({
series: [
{
data: [], //
},
],
});
myChart2.setOption({
series: [
{
data: [], //
},
],
});
Object.keys(res.data.dataSet).forEach((key) => {
const bgColor = getRandomColorHex();
addData(myChart, res.data.dataSet[key], bgColor);
addData(myChart2, res.data.dataSet[key], bgColor);
});
Object.keys(res.data.centroid).forEach((key) => {
addData(myChart2, res.data.centroid[key], "red");
newItem["TSuid"] = sex;
sex++;
tableData3.value.push(newItem);
tableData3.value[index].children = [];
const children = ref([]);
item.forEach((item2, sexx) => {
const newItem2 = {};
tableLabel.forEach((label, index2) => {
newItem2[label.prop] = item2[index2]; //
});
newItem2["TSuid"] = "" + sex + sexx;
children.value.push(newItem2);
});
tableData3.value[index].children = children.value;
console.log(tableData3.value);
});
})
.then(() => {
API.clusterAnalysis(sendData).then((res) => {
myChart.setOption({
series: [
{
data: [], //
},
],
});
myChart2.setOption({
series: [
{
data: [], //
},
],
});
Object.keys(res.data.dataSet).forEach((key) => {
const bgColor = getRandomColorHex();
addData(myChart, res.data.dataSet[key], bgColor);
addData(myChart2, res.data.dataSet[key], bgColor);
});
Object.keys(res.data.centroid).forEach((key) => {
addData(myChart2, res.data.centroid[key], "red");
});
});
nextTick(() => {
setTimeout(() => {
const scrollContainer = scrollbar.value?.$el.querySelector(".el-scrollbar__wrap");
if (scrollContainer) {
scrollContainer.scrollTo({
top: scrollContainer.scrollHeight,
behavior: "smooth", //
});
}
}, 100);
});
} else {
proxy.$modal.msgWarning("请模型参数进行设置!");
}
};
const exportTableRef = ref(null);
const upLoad = () => {
const tableDom = exportTableRef.value?.$el;
if (!tableDom) {
return;
}
const wb = XLSX.utils.table_to_book(tableDom);
// XLSX.writeFile(wb, '.xlsx');
const zip = new JSZip();
const excelBlob = XLSX.write(wb, { bookType: "xlsx", type: "array" });
zip.file("聚类分析.xlsx", new Blob([excelBlob], { type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" }));
zip.file("聚类分析图表.pdf", handleExport());
zip.generateAsync({ type: "blob" }).then((content) => {
saveAs(content, "聚类分析.zip");
});
};
const startOver = () => {
myChart.setOption({
series: [
{
data: [], //
},
],
});
myChart2.setOption({
series: [
{
data: [], //
},
],
nextTick(() => {
setTimeout(() => {
const scrollContainer = scrollbar.value?.$el.querySelector(".el-scrollbar__wrap");
if (scrollContainer) {
scrollContainer.scrollTo({
top: scrollContainer.scrollHeight,
behavior: "smooth", //
});
}
}, 100);
});
input.value = "";
tableData.value = [];
tableData2.value = [];
tableData3.value = [];
input2.value = "";
input3.value = "";
input4.value = "";
input5.value = "";
input6.value = "";
showChart.value = false;
tableLabel.length = 0;
nowData.value = [];
};
//pdf
const handleExport = async (name) => {
var fileName = "聚类分析图表";
const fileList = document.getElementsByClassName("pdfRef"); //
const pdfBlob = await htmlPdf(fileName, document.querySelector("#pdfRef"), fileList, true);
return pdfBlob;
};
} else {
proxy.$modal.msgWarning("请模型参数进行设置!");
}
};
const exportTableRef = ref(null);
const upLoad = () => {
const tableDom = exportTableRef.value?.$el;
if (!tableDom) {
return;
}
const wb = XLSX.utils.table_to_book(tableDom);
// XLSX.writeFile(wb, '.xlsx');
const zip = new JSZip();
const excelBlob = XLSX.write(wb, { bookType: "xlsx", type: "array" });
zip.file("聚类分析.xlsx", new Blob([excelBlob], { type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" }));
zip.file("聚类分析图表.pdf", handleExport());
zip.generateAsync({ type: "blob" }).then((content) => {
saveAs(content, "聚类分析.zip");
});
};
const startOver = () => {
myChart.setOption({
series: [
{
data: [], //
},
],
});
myChart2.setOption({
series: [
{
data: [], //
},
],
});
input.value = "";
tableData.value = [];
tableData2.value = [];
tableData3.value = [];
input2.value = "";
input3.value = "";
input4.value = "";
input5.value = "";
input6.value = "";
showChart.value = false;
tableLabel.length = 0;
nowData.value = [];
};
//pdf
const handleExport = async (name) => {
var fileName = "聚类分析图表";
const fileList = document.getElementsByClassName("pdfRef"); //
const pdfBlob = await htmlPdf(fileName, document.querySelector("#pdfRef"), fileList, true);
return pdfBlob;
};
</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: #e6e6e6">给出任务清单参考做哪些数据的统计分析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">给出任务清单参考做哪些数据的统计分析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>
</div>
<div class="main-but">
<el-button @click="knowledgeImport">
@ -70,7 +70,11 @@
<div>
<span style="font-weight: bold; font-size: 18px; color: #3596eb">分析数据</span>
<el-table :data="analysisData" style="width: 100%; margin-top: 10px" :header-cell-style="headerCellStyle">
<el-table-column v-for="column in analysisHanderKry" :key="column" :prop="column" :label="column" align="center" />
<el-table-column v-for="column in analysisHanderKry" :key="column" :prop="column" :label="column" align="center">
<template #default="scope">
<span>{{ scope.row[column] ?? "..." }}</span>
</template>
</el-table-column>
</el-table>
<pagination v-show="n_analyzeTheNumberOfDataItems > 0" :total="n_analyzeTheNumberOfDataItems" v-model:page="n_dataTableQuery.index" v-model:limit="n_dataTableQuery.size" @pagination="analyzeDataNext" />
</div>
@ -78,7 +82,11 @@
<span style="font-weight: bold; font-size: 18px; color: #3596eb; display: block">分析结果</span>
<el-button @click="download"></el-button>
<el-table :data="tableData" style="width: 100%; margin-top: 10px" :header-cell-style="headerCellStyle" height="350" v-loading="loading">
<el-table-column v-for="column in tableLabel" :key="column.label" :prop="column.prop" :label="column.label" align="center"></el-table-column>
<el-table-column v-for="column in tableLabel" :key="column.label" :prop="column.prop" :label="column.label" align="center">
<template #default="scope">
<span>{{ scope.row[column.prop] ?? "..." }}</span>
</template>
</el-table-column>
</el-table>
<pagination v-show="nNumberOfAnalysisResults > 0" :total="nNumberOfAnalysisResults" v-model:page="gAnalysisResults.index" v-model:limit="gAnalysisResults.size" @pagination="updatePageAnalysisResults" />
</div>
@ -428,7 +436,7 @@ function processArrayData(keys, data) {
//
keys.forEach((key) => {
// data
const values = data.map((item) => item[key]);
const values = data.map((item) => item[key] ?? "0");
//
result[key] = values;
});
@ -484,14 +492,14 @@ const restart = () => {
observations: "",
};
analysisData.value = [];
analysisHanderKry.value = [];
analysisHanderKry.value = [""];
tableData.value = [];
g_indicatorData.value = [];
g_modelParameter.value = [];
preProcessText.value.text2 = "";
n_dataTableQuery.value.tableName = "用户属性表";
getIndicator();
proxy.$modal.msgSuccess("重新开始成功");
proxy.$modal.msgSuccess("重新开始!");
multipleTableRef.value.clearSelection();
};
//

@ -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: #e6e6e6">给出任务清单参考做哪些数据的统计分析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">给出任务清单参考做哪些数据的统计分析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>
</div>
<div class="main-but">
<el-button @click="knowledgeImport">
@ -21,7 +21,7 @@
</div>
<div class="metrics">
<el-select v-model="n_dataTableQuery.tableName" placeholder="请选择数据" style="width: 180px" @change="selectType">
<el-option v-for="item in algorithmStore.userDataLabel" :key="item" :label="item" :value="item" />
<el-option v-for="item in algorithmStore.userDataLabel2" :key="item" :label="item" :value="item" />
</el-select>
</div>
<div class="metrics-table" style="margin-top: 10px">
@ -82,7 +82,7 @@
</div>
<div class="analysisResults" style="margin-top: 20px">
<span style="font-weight: bold; font-size: 18px; color: #3596eb; display: block">分析结果</span>
<el-button v-if="preProcessText.text3 !== '词云生成'" @click="download"></el-button>
<el-button v-if="preProcessText.text3 !== '词云生成'" @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>
@ -107,15 +107,15 @@
<div class="div" v-if="preProcessText.text3 == '词云生成'">
<div id="mywordcloud_positive" style="width: 50%; height: 600px"></div>
</div>
<div ref="captureElement" v-if="preProcessText.text3 == '情感倾向分析' && n_emotiveTendency == 0 ? true : g_emotionAnalysis">
<div ref="captureElement" v-if="preProcessText.text3 == '情感倾向分析' && n_emotiveTendency == 0 ? true : 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'" />
<el-progress :class="[g_emotionAnalysis == 0 ? 'negPercentage ' : '']" style="width: 480px" :text-inside="true" :stroke-width="20" :percentage="n_emotiveTendency" :color="'#ff540a'" />
<div class="emotion_analysis-ani-in-ri">
<img src="" alt="" />
<img src="../../../assets/images/哭脸.png" alt="" />
<span>负向情感</span>
</div>
<div class="emotion_analysis_title">{{ g_emotionAnalysis == 0 ? "情感偏负向" : g_emotionAnalysis == 1 ? "情感偏中性" : "情感偏正向" }}</div>
@ -162,7 +162,7 @@
</el-form-item>
</el-form-item>
<el-form-item label="情感倾向分析: " label-width="120px">
<el-radio-group v-model="formInline.emotional" style="margin-left: 31px">
<el-radio-group v-model="formInline.emotional" style="margin-left: 31px" fill="red" text-color="#ffffff">
<el-radio value="1" label="正向" size="large"></el-radio>
<el-radio value="2" label="负向" size="large"></el-radio>
</el-radio-group>
@ -184,7 +184,7 @@
<popModel :showModel="b_algorithmKnowledge" title="情感分析" @closePop="b_algorithmKnowledge = false">
<template v-slot:content>
<!-- 情感分析 -->
<div>
<div style="color: #000000 !important">
<p style="font-weight: 700; font-size: 22px">总览</p>
<p>
文本分析指对文本数据进行表示 (representation)处理(processing)和建模(modeling)来获得有用的见解(insight)
@ -413,7 +413,6 @@
</template>
<script setup>
import popModel from "@/views/components/popModal.vue";
import { paginate } from "@/utils/index.js";
import * as echarts from "echarts";
import * as XLSX from "XLSX";
@ -424,7 +423,6 @@ 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 b_algorithmKnowledge = ref(false);
@ -434,7 +432,6 @@ const loading2 = ref(false);
const { proxy } = getCurrentInstance();
const algorithmStore = useAlgorithmStore();
const multipleTableRef = ref(null);
const b_introductionOfAlgorithmKnowledge = ref(false);
const n_dataTableQuery = ref({
index: 1,
size: 5,
@ -487,7 +484,6 @@ const preProcessText = ref({
const aOriginalDataOfAnalysisResults2 = ref({});
const nOriginalWordFrequency = ref([]); //
const nOriginalWordFrequencyNum = ref(0); //
const nOriginalWordFrequencySearch = ref([]); //
const mWordFrequency = ref({
index: 1,
size: 10,
@ -498,10 +494,13 @@ const mWordFrequency = ref({
//
const g_analyzeTheNumberOfDataItems = ref("");
//
const g_modelParameter = ref([]);
const n_emotiveTendency = ref(0);
const g_emotionAnalysis = ref(0);
const aCommentOpinion = ref([]);
//
const downloadStatus = ref(false);
//
//
const preProcess = (tetx) => {
if (g_indicatorData.value.length == 0) {
@ -523,7 +522,6 @@ const preProcess = (tetx) => {
const taskSubmit = () => {
dialogVisible.value = true;
};
const tableData = ref([]);
const headerCellStyle = () => {
return {
backgroundColor: "#1882DE !important", //
@ -544,47 +542,25 @@ 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(",");
// g_analyzeTheNumberOfDataItems.value =
if (
res.data
.map((item) => (item ? item.text : ""))
.every((item) => {
return item !== "";
})
) {
g_analyzeTheNumberOfDataItems.value = res.data.map((item) => (item ? item.text : "")).join(",");
} else {
g_analyzeTheNumberOfDataItems.value = "";
loading.value = false;
return;
}
analysisData.value = res.data.filter((item) => item !== null);
loading.value = false;
proxy.$modal.msgSuccess("分析数据成功");
});
};
//
const handlemodelSelectionChange = (type) => {
g_modelParameter.value = type.map((item) => item.name);
};
//
const modelCalculation = () => {
if (analysisData.value.length == 0 && g_modelParameter.value.length == 0) {
proxy.$modal.msgWarning("请先分析数据/未选择模型参数!");
return;
}
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) {
nNumberOfAnalysisResults.value = res.data.length;
aOriginalDataOfAnalysisResults.value = res.data.map((item) => item.statistics);
tableData.value = res.data.map((item) => item.statistics).slice(0, 5);
}
});
};
function processArrayData(keys, data) {
//
const result = {};
//
keys.forEach((key) => {
// data
const values = data.map((item) => item[key]);
//
result[key] = values;
});
return result;
}
onMounted(() => {
getIndicator();
});
@ -620,35 +596,42 @@ const submitTask = () => {
const restart = () => {
//
formInline.value = {
average: "",
median: "",
mode: "",
standardDeviation: "",
variance: "",
standardError: "",
kurtosis: "",
skewness: "",
max: "",
min: "",
summation: "",
observations: "",
frequency: "",
text1: "",
text2: "",
emotional: "",
prominent: "",
};
analysisData.value = [];
g_analyzeTheNumberOfDataItems.value = "";
analysisHanderKry.value = [];
tableData.value = [];
g_indicatorData.value = [];
g_modelParameter.value = [];
preProcessText.value.text2 = "";
n_dataTableQuery.value.tableName = "用户属性表";
getIndicator();
proxy.$modal.msgSuccess("重新开始成功");
preProcessText.value = {
text1: "数据去重",
text2: "",
text3: "",
};
aOriginalDataOfAnalysisResults2.value = {};
mWordFrequency.value = {
index: 1,
size: 10,
namenum: "",
frequency: "",
};
n_emotiveTendency.value = 0;
aCommentOpinion.value = [];
nOriginalWordFrequencyNum.value = 0;
aWordFrequency.value = [];
nOriginalWordFrequency.value = [];
s_commentType.value = "";
proxy.$modal.msgSuccess("重新开始!");
multipleTableRef.value.clearSelection();
};
const captureElement = ref(null);
//
const download = async () => {
// let tableData = ["", ""];
// XLSX.utils.aoa_to_sheet(tableData);
if (!downloadStatus.value) return proxy.$modal.msgWarning("请先分析数据!");
if (preProcessText.value.text3 == "情感倾向分析" || preProcessText.value.text3 == "评论观点抽取") {
if (captureElement.value) {
try {
@ -703,41 +686,66 @@ const sentimentAnalysis = () => {
}
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);
console.log(n_emotiveTendency.value, " n_emotiveTendency.value");
} 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("分析成功");
})
.catch((err) => {
loading.value = false;
});
if (preProcessText.value.text3 === "情感倾向分析") {
marketingAlgorithmApi
.getMarketingAlgorithmSentimentAnalysis(JSON.stringify({ text: g_analyzeTheNumberOfDataItems.value }))
.then((res) => {
g_emotionAnalysisinfo = res.data;
const pos = parseFloat(g_emotionAnalysisinfo.pos);
const neg = parseFloat(g_emotionAnalysisinfo.neg);
const total = pos + neg;
const posPercentage = total !== 0 ? (pos / total) * 100 : 0;
const negPercentage = total !== 0 ? (neg / total) * 100 : 0;
if (posPercentage > negPercentage) {
g_emotionAnalysis.value = 2;
n_emotiveTendency.value = posPercentage;
} else if (negPercentage > posPercentage) {
g_emotionAnalysis.value = 0;
n_emotiveTendency.value = negPercentage;
}
if (posPercentage == negPercentage) {
g_emotionAnalysis.value = 1;
n_emotiveTendency.value = 50;
}
loading.value = false;
})
.catch((err) => {
loading.value = false;
});
} else {
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 {
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;
loading.value = false;
proxy.$modal.msgSuccess("分析成功");
})
.catch((err) => {
loading.value = false;
});
}
};
//
const clear = () => {
if (!g_analyzeTheNumberOfDataItems.value) return proxy.$modal.msgWarning("请先分析数据!");
g_analyzeTheNumberOfDataItems.value = "";
aWordFrequency.value = [];
proxy.$modal.msgSuccess("清空成功");
@ -966,6 +974,24 @@ const switchingModels = () => {
.footer {
padding-top: 20px;
text-align: center;
.el-button {
width: 110px;
height: 31px;
color: #333333;
border: none;
//
&:focus {
outline: none;
}
}
.el-button:nth-child(1) {
background: url("../../../assets/images/情感分析.png") no-repeat;
background-size: 100% 100%;
}
.el-button:nth-child(2) {
background: url("../../../assets/images/取消.png") no-repeat;
background-size: 100% 100%;
}
}
}
.metrics,
@ -1055,9 +1081,17 @@ const switchingModels = () => {
font-size: 24px;
font-weight: normal;
}
:deep(.el-progress) {
position: relative;
}
:deep(.el-progress-bar__outer) {
background-color: #036fe2;
}
:deep(.negPercentage) {
.el-progress-bar__inner {
background-color: #036fe2 !important;
}
}
}
.comment-opinion {
padding: 30px 20px 0px 90px !important;
@ -1152,8 +1186,8 @@ const switchingModels = () => {
}
h4,
p {
color: #ffffff !important;
font-size: 14px;
// color: #ffffff !important;
// font-size: 14px;
}
:deep(.pagination-container .el-pagination) {
//
@ -1164,4 +1198,22 @@ p {
flex-wrap: nowrap !important;
}
}
:deep(.el-radio-group) {
//
.is-checked.el-radio__label {
color: #ffffff !important;
}
.el-radio__input.is-checked .el-radio__inner {
background: #2d5c8f !important;
border-color: #2d5c8f !important;
}
.el-radio__label {
color: #ffffff !important;
}
.el-radio__input .el-radio__inner {
background: #2d5c8f !important;
border-color: #2d5c8f !important;
border-color: #6fa8de !important;
}
}
</style>

@ -2,7 +2,7 @@
<!-- <el-scrollbar ref="scrollbar" height="800px"> -->
<div class="main-top">
<span style="font-weight: bold; font-size: 18px; color: #3596eb">任务描述</span>
<p style="font-weight: 400; font-size: 12px; color: #e6e6e6">给出任务清单参考做哪些数据的统计分析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">给出任务清单参考做哪些数据的统计分析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>
</div>
<div class="main-but">
<el-button @click="runResultShow = true">

@ -1,44 +1,44 @@
<template>
<div class="login" v-loading="loading">
<div class="login-main">
<el-form ref="loginRef" :model="loginForm" :rules="loginRules" class="login-form">
<h3 class="title">数字营销</h3>
<el-form-item prop="username">
<el-input v-model="loginForm.username" type="text" size="large" auto-complete="off" placeholder="账号">
<template #prefix><svg-icon icon-class="user" class="el-input__icon input-icon" /></template>
</el-input>
</el-form-item>
<el-form-item prop="password">
<el-input v-model="loginForm.password" type="password" size="large" auto-complete="off" placeholder="密码" @keyup.enter="handleLogin" show-password>
<template #prefix><svg-icon icon-class="password" class="el-input__icon input-icon" /></template>
</el-input>
</el-form-item>
<el-checkbox v-model="loginForm.rememberMe" style="margin: 0px 0px 25px 0px"></el-checkbox>
<el-form-item style="width: 100%">
<el-button :loading="loading" size="large" type="primary" style="width: 100%" @click.prevent="handleLogin">
<span v-if="!loading"> </span>
<span v-else> ...</span>
</el-button>
<div style="float: right" v-if="register">
<router-link class="link-type" :to="'/register'">立即注册</router-link>
</div>
</el-form-item>
</el-form>
</div>
<!-- 底部 -->
<div class="el-login-footer" style="display: none">
<span>Copyright © 2018-2023 ruoyi.vip All Rights Reserved.</span>
</div>
<div class="login-main">
<el-form ref="loginRef" :model="loginForm" :rules="loginRules" class="login-form">
<h3 class="title">数字营销</h3>
<el-form-item prop="username">
<el-input v-model="loginForm.username" type="text" size="large" auto-complete="off" placeholder="账号">
<template #prefix><svg-icon icon-class="user" class="el-input__icon input-icon" /></template>
</el-input>
</el-form-item>
<el-form-item prop="password">
<el-input v-model="loginForm.password" type="password" size="large" auto-complete="off" placeholder="密码" @keyup.enter="handleLogin" show-password>
<template #prefix><svg-icon icon-class="password" class="el-input__icon input-icon" /></template>
</el-input>
</el-form-item>
<el-checkbox v-model="loginForm.rememberMe" style="margin: 0px 0px 25px 0px"></el-checkbox>
<el-form-item style="width: 100%">
<el-button :loading="loading" size="large" type="primary" style="width: 100%" @click.prevent="handleLogin">
<span v-if="!loading"> </span>
<span v-else> ...</span>
</el-button>
<div style="float: right" v-if="register">
<router-link class="link-type" :to="'/register'">立即注册</router-link>
</div>
</el-form-item>
</el-form>
</div>
<!-- 底部 -->
<div class="el-login-footer" style="display: none">
<span>Copyright © 2018-2023 ruoyi.vip All Rights Reserved.</span>
</div>
</div>
</template>
<script setup>
import { getCodeImg } from "@/api/login";
import Cookies from "js-cookie";
import { encrypt, decrypt } from "@/utils/jsencrypt";
import useUserStore from '@/store/modules/user'
import useUserStore from "@/store/modules/user";
const userStore = useUserStore()
const userStore = useUserStore();
const route = useRoute();
const router = useRouter();
const { proxy } = getCurrentInstance();
@ -48,63 +48,68 @@ const loginForm = ref({
password: "",
rememberMe: false,
code: "",
uuid: ""
uuid: "",
});
const loginRules = {
username: [{ required: true, trigger: "blur", message: "请输入您的账号" }],
password: [{ required: true, trigger: "blur", message: "请输入您的密码" }],
code: [{ required: true, trigger: "change", message: "请输入验证码" }]
code: [{ required: true, trigger: "change", message: "请输入验证码" }],
};
const codeUrl = ref("");
const loading = ref(false);
//
const captchaEnabled = ref(true);
//
//
const register = ref(false);
const redirect = ref(undefined);
watch(route, (newRoute) => {
watch(
route,
(newRoute) => {
redirect.value = newRoute.query && newRoute.query.redirect;
}, { immediate: true });
},
{ immediate: true }
);
function handleLogin() {
// proxy.$refs.loginRef.validate(valid => {
// if (valid) {
loading.value = true;
// cookie
if (loginForm.value.rememberMe) {
Cookies.set("username", loginForm.value.username, { expires: 30 });
Cookies.set("password", encrypt(loginForm.value.password), { expires: 30 });
Cookies.set("rememberMe", loginForm.value.rememberMe, { expires: 30 });
// if (valid) {
loading.value = true;
// cookie
if (loginForm.value.rememberMe) {
Cookies.set("username", loginForm.value.username, { expires: 30 });
Cookies.set("password", encrypt(loginForm.value.password), { expires: 30 });
Cookies.set("rememberMe", loginForm.value.rememberMe, { expires: 30 });
} else {
//
Cookies.remove("username");
Cookies.remove("password");
Cookies.remove("rememberMe");
}
//
const params = {
username: loginForm.value.username,
password: loginForm.value.password !== "" ? encrypt(loginForm.value.password) : loginForm.value.password,
token: loginForm.value.TOKEN,
};
userStore
.login(params)
.then((res) => {
router.push({ path: redirect.value || "/index" });
if (params.token) {
setTimeout(() => {
loading.value = false;
}, 3000);
} else {
//
Cookies.remove("username");
Cookies.remove("password");
Cookies.remove("rememberMe");
loading.value = false;
}
//
const params = {
username: loginForm.value.username,
password: loginForm.value.password !== '' ? encrypt(loginForm.value.password) : loginForm.value.password,
token: loginForm.value.TOKEN,
};
userStore
.login(params)
.then(res => {
router.push({ path: redirect.value || '/index' });
if (params.token) {
setTimeout(() => {
loading.value = false;
}, 3000);
} else {
loading.value = false;
}
}).catch(() => {
loading.value = false;
});
// }
})
.catch(() => {
loading.value = false;
});
// }
// });
}
@ -125,7 +130,7 @@ function getCookie() {
loginForm.value = {
username: username === undefined ? loginForm.value.username : username,
password: password === undefined ? loginForm.value.password : decrypt(password),
rememberMe: rememberMe === undefined ? false : Boolean(rememberMe)
rememberMe: rememberMe === undefined ? false : Boolean(rememberMe),
};
}
@ -133,74 +138,74 @@ function getCookie() {
getCookie();
</script>
<style lang='scss' scoped>
.login {
display: flex;
justify-content: center;
align-items: center;
height: 100%;
background-image: url('@/assets/images/login-background.0dded3b4.webp');
background-size: 100% 100%;
}
.title {
margin: 0px auto 30px auto;
text-align: center;
color: rgb(48, 50, 52);
font-size: 22px;
font-weight: 500;
}
.login-main {
width: 85%;
height: 100%;
display: flex;
align-items: center;
justify-content: end;
}
.login-form {
border-radius: 6px;
background: #ffffff;
width: 400px;
padding: 55px 25px 33px 25px;
.el-input {
height: 40px;
input {
height: 40px;
}
}
.input-icon {
height: 39px;
width: 14px;
margin-left: 0px;
}
}
.login-tip {
font-size: 13px;
text-align: center;
color: #bfbfbf;
}
.login-code {
width: 33%;
height: 40px;
float: right;
img {
cursor: pointer;
vertical-align: middle;
}
}
.el-login-footer {
height: 40px;
line-height: 40px;
position: fixed;
bottom: 0;
width: 100%;
text-align: center;
color: #fff;
font-family: Arial;
font-size: 12px;
letter-spacing: 1px;
}
.login-code-img {
height: 40px;
padding-left: 12px;
<style lang="scss" scoped>
.login {
display: flex;
justify-content: center;
align-items: center;
height: 100%;
background-image: url("@/assets/images/login-background.0dded3b4.webp");
background-size: 100% 100%;
}
.title {
margin: 0px auto 30px auto;
text-align: center;
color: rgb(48, 50, 52);
font-size: 22px;
font-weight: 500;
}
.login-main {
width: 85%;
height: 100%;
display: flex;
align-items: center;
justify-content: end;
}
.login-form {
border-radius: 6px;
background: #ffffff;
width: 400px;
padding: 55px 25px 33px 25px;
.el-input {
height: 40px;
input {
height: 40px;
}
}
.input-icon {
height: 39px;
width: 14px;
margin-left: 0px;
}
}
.login-tip {
font-size: 13px;
text-align: center;
color: #bfbfbf;
}
.login-code {
width: 33%;
height: 40px;
float: right;
img {
cursor: pointer;
vertical-align: middle;
}
}
.el-login-footer {
height: 40px;
line-height: 40px;
position: fixed;
bottom: 0;
width: 100%;
text-align: center;
color: #fff;
font-family: Arial;
font-size: 12px;
letter-spacing: 1px;
}
.login-code-img {
height: 40px;
padding-left: 12px;
}
</style>

Loading…
Cancel
Save