front/src/views/ShowGraph.vue

683 lines
19 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<el-header class = 'containerHead'>
<HeaderPage :pageTitle = 'pageTitle'></HeaderPage>
<el-button class = 'btnReturnHomePage' @click="returnHome">
<el-tooltip content = '返回首页'>
<el-icon><ArrowLeft /></el-icon>
</el-tooltip>
</el-button>
</el-header>
<el-container>
<div class="container">
<div class="left-grid">
<el-card>
<el-row>
<el-form>
<div class="demo-select">
<div class="block">
<span class="demonstration">数据可视化</span>
<el-select v-model="selectedEntity" placeholder="选择实体">
<el-option
v-for="entity in entityOptions"
:key="entity.value"
:label="entity.label"
:value="entity.value"
></el-option>
</el-select>
</div>
</div>
<!-- 动态输入组件 -->
<component
:is="currentComponent"
ref="dynamicComponent"
@change="handlerow"
@update:selectedEntity="handleSelectedEntity"
@update:selectedrow="handleSelectedRow"
@update:selectedChartType="handleSelectedChartType"
@update:selectedrow2="handleSelectedRow2"
:rowOptions="convertedColumns"
:rowOptions2="convertedColumns"
>
</component>
<el-form-item>
<el-button type="primary" size="medium" @click="handleGenerateChart">
点击生成图表
</el-button>
</el-form-item>
</el-form>
</el-row>
</el-card>
</div>
<div class="right-grid">
<div class="upper-right" v-if="hasUpperContent">
<el-button type="danger" @click="clearchart">取消</el-button>
<div ref="chartContainer" class="chart-container"></div>
</div>
<div class="lower-right">
</div>
</div>
</div>
</el-container>
</template>
<script>
import { useRouter } from 'vue-router';
import * as echarts from 'echarts';
import Entity1Form from '@/components/graph/Entity1Form.vue';
import Entity2Form from '@/components/graph/Entity2Form.vue';
import Entity3Form from '@/components/graph/Entitu3Form.vue';
import Entity4Form from '@/components/graph/Entity4Form.vue';
import Entity5Form from '@/components/graph//Entity5Form.vue';
import HeaderPage from "@/components/HeaderPage.vue";
export default {
components: {
Entity1Form,
Entity2Form,
Entity3Form,
Entity4Form,
Entity5Form,
HeaderPage
},
props: ['columns','tabledata'],
data() {
return {
xz:[],
yz:[],
pageTitle:'图形可视化',
mytable:[],
mycolumns:'',
item:[],
records:[],
inputStr:[],
Rdata: [], // 示例数据,可以替换为实际数据
interval: '', // 间隔x可以根据需求调整
stype:'',
srow:'',
srow2:'',
gap:'',
monthKey:'',
chartType: 'bar',
hasUpperContent: false,
chartInstance: null ,// 存储图表实例的引用
selectedEntity: '', // 默认选中的实体
entityOptions: [
{ value: 'entity1', label: '某年/月/日开始的线索' },
{value:'entity2',label:'某年/月/日正在进行的线索'},
{ value: 'entity3', label: '实数区间' },
{ value: 'entity4', label: '实体线索数或其他指标统计' },
{
value: 'entity5', label: '三维数据'
},
],
dates: [],
};
},
// watch: {
// mytable: {
// handler(newVal, oldVal) {
// console.log('mytable changed');
// console.log('New Value:', newVal);
// console.log('Old Value:', oldVal);
// // 在这里可以添加你希望在mytable变化时执行的逻辑
// },
// deep: true // 如果需要深度监听对象内部的变化可以设置deep为true
// }
// },
computed: {
convertedColumns() {
return this.mycolumns.map(item => {
return { value: item.prop, label: item.label };
})
},
currentComponent() {
switch (this.selectedEntity) {
case 'entity1':
return 'Entity1Form';
case 'entity2':
return 'Entity2Form';
case 'entity3':
return 'Entity3Form';
case 'entity4':
return 'Entity4Form';
case 'entity5':
return 'Entity5Form';
default:
return null;
}
}
},
created()
{
console.log(this.$route.params.tabledata)
this.mytable=JSON.parse(this.$route.params.tabledata);
this.mycolumns = JSON.parse(this.$route.params.columns);
console.log('Parsed columns:', this.mycolumns,this.table);
},
methods: {
returnHome(){
window.history.back();
},
countsumbystring() {
// 创建一个对象来存储每个名字对应的实数总和
this.hasUpperContent = true;
const sumByName = {};
// 遍历数据数组,累加同名字的实数
this.item.forEach(item => {
const name = item[0];
const number = parseFloat(item[1]);
// 如果该名字还没有在 sumByName 对象中,则初始化为 0
if (!sumByName[name]) {
sumByName[name] = number;
}
// 累加实数
sumByName[name] += number;
})
// 返回结果对象
return sumByName;
},
handlerow()
{
this.srow='';
this.srow2='';
},
calculateMonthlyRecords() {
// 假设你有一个包含所有记录的表格,存储在一个数组中
this.hasUpperContent = true;
// 创建一个对象来存储每个月的记录条数
this.records.sort((a, b) => {
const startDateA = new Date(a[0]);
const startDateB = new Date(b[0]);
return startDateA - startDateB;
});
const monthlyRecords = {};
const cords=this.records;
cords.sort((a,b)=>{const endDateA=new Date(a[1]);
const endDateB=new Date(b[1]);
return endDateB-endDateA;
})
// 遍历每一条记录
const startDate1 = new Date(this.records[0][0]);
//初始化
const endDate1 = new Date(this.records[0][1]);
const currentDate = new Date(startDate1);
while (currentDate <= endDate1) {
if (this.gap === 'month') {
let monthKey = `${currentDate.getFullYear()}-${currentDate.getMonth() + 1}`;
monthlyRecords[monthKey] = 0;
currentDate.setMonth(currentDate.getMonth() + 1);
} else if (this.gap === 'year') {
let yearKey = `${currentDate.getFullYear()}`;
monthlyRecords[yearKey] = 0;
currentDate.setFullYear(currentDate.getFullYear() + 1);
} else {
let dayKey = `${currentDate.getFullYear()}-${currentDate.getMonth() + 1}-${currentDate.getDate()}`;
monthlyRecords[dayKey] = 0;
currentDate.setDate(currentDate.getDate()+1);
}
}
for (var i = 0; i < this.records.length; i++) {
const record = this.records[i];
var startDate = new Date(record[0]);
var endDate = new Date(record[1]);
// 遍历开始日期到结束日期之间的每个月
if (this.gap=="month"){
const currentMonth = new Date(startDate.getFullYear(), startDate.getMonth(), 1);
while (currentMonth <= endDate) {
const monthKey1 = currentMonth.getFullYear() + '-' + (currentMonth.getMonth() + 1);
// 如果该月份不存在于monthlyRecords对象中则创建并初始化为0
if (!monthlyRecords[monthKey1]) {
monthlyRecords[monthKey1] = 1;
}
// 增加该月份的记录条数
monthlyRecords[monthKey1]++;
// 下一个月
currentMonth.setMonth(currentMonth.getMonth() + 1);
}
}else if (this.gap=='year'){
const currentyear = new Date(startDate.getFullYear(), 1, 1);
while (currentyear <= endDate) {
const monthKey1 = currentyear.getFullYear() ;
// 如果该月份不存在于monthlyRecords对象中则创建并初始化为0
if (!monthlyRecords[monthKey1]) {
monthlyRecords[monthKey1] = 1;
}
// 增加该月份的记录条数
monthlyRecords[monthKey1]++;
// 下一个月
currentyear.setFullYear(currentyear.getFullYear()+1);
}
}
else
{
const currentday=new Date(startDate.getFullYear(), startDate.getMonth(), startDate.getDate());
while (currentday <= endDate) {
const monthKey1 = currentday.getFullYear() + '-' + (currentday.getMonth() + 1)+(currentday.getDate());
// 如果该月份不存在于monthlyRecords对象中则创建并初始化为0
if (!monthlyRecords[monthKey1]) {
monthlyRecords[monthKey1] = 1;
}
// 增加该月份的记录条数
monthlyRecords[monthKey1]++;
// 下一个月
currentday.setDate(currentday.getDate() + 1);
}
}
}
// 返回每个月的记录条数对象
return monthlyRecords;
},
countStrings() {
// Initialize the object to hold string counts
this.hasUpperContent = true;
const stringCounts = {};
// Split the input string by newlines, trim whitespace, and filter out empty strings
const strings = this.inputStr;
// Iterate over each string and count occurrences
strings.forEach(str => {
if (stringCounts[str]) {
stringCounts[str]++;
} else {
stringCounts[str] = 1;
}
});
// Update the component's data with the computed string counts
return stringCounts;
},
handleSelectedEntity(value) {
console.log('Selected Entity:', value);
// 在这里处理接收到的 selectedEntity 值
this.interval=value;
this.gap=value;
},
handleSelectedRow(value) {
console.log('Selected Row:', value);
// 在这里处理接收到的 selectedrow 值
this.srow=value
},
handleSelectedRow2(value) {
console.log('Selected Row2:', value);
this.srow2=value
},
handleSelectedChartType(value) {
console.log('Selected Chart Type:', value);
this.stype=value;
// 在这里处理接收到的 selectedChartType 值
},
countMonth(){
this.hasUpperContent = true;
this.dates.sort((a, b) => new Date(a) - new Date(b));
const monthCount = {};
const startDate = new Date(this.dates[0]);
//初始化
const endDate = new Date(this.dates[this.dates.length - 1]);
const currentDate = new Date(startDate);
while (currentDate <= endDate) {
if (this.gap === 'month') {
const monthKey = `${currentDate.getFullYear()}-${currentDate.getMonth() + 1}`;
monthCount[monthKey] = 0;
currentDate.setMonth(currentDate.getMonth() + 1);
} else if (this.gap === 'year') {
const yearKey = `${currentDate.getFullYear()}`;
monthCount[yearKey] = 0;
currentDate.setFullYear(currentDate.getFullYear() + 1);
} else {
const dayKey = `${currentDate.getFullYear()}-${currentDate.getMonth() + 1}-${currentDate.getDate()}`;
monthCount[dayKey] = 0;
currentDate.setDate(currentDate.getDate()+1);
}
}
for (const dateStr of this.dates) {
const date = new Date(dateStr);
if (this.gap=='month'){
this.monthKey = `${date.getFullYear()}-${date.getMonth() + 1}`;
}else if(this.gap=='year'){
this.monthKey = `${date.getFullYear()}`;
}else
{
this.monthKey = `${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}`;
}
if (monthCount[this.monthKey]) {
monthCount[this.monthKey]++;
} else {
monthCount[this.monthKey] = 1;
}
}
// Format data for ECharts
const xAxisData = [];
const seriesData = [];
for (const key in monthCount) {
if (Object.prototype.hasOwnProperty.call(monthCount, key)) {
xAxisData.push(key);
seriesData.push(monthCount[key]);
}
}
return monthCount;
},
countDataByInterval() {
this.hasUpperContent = true;
this.Rdata.sort((a, b) => a - b);
const counts = {};
const interval = this.interval;
this.Rdata.forEach((number) => {
const index = Math.floor(number / interval);
const key = `${index * interval}-${(index + 1) * interval}`;
if (counts[key]) {
counts[key]++;
} else {
counts[key] = 1;
}
});
return counts;
},
drawChart(counts) {
try
{
const chartContainer = this.$refs.chartContainer;
this.chartInstance = echarts.init(chartContainer);
let option;
if (this.stype === 'bar' || this.stype == 'line') {
option = {
xAxis: {
type: 'category',
data: Object.keys(counts),
name: '区间',
axisLabel:
{
frontSize:12,
interval:0,
rotate:30
}
},
yAxis: {
type: 'value',
},
series: [{
data: Object.values(counts),
type: this.stype,
}],
};
} else if (this.stype === 'pie') {
const data = Object.entries(counts).map(([name, value]) => ({ value, name }));
option = {
series: [{
type: 'pie',
radius: '60%',
data,
}],
xAxis: { show: false }, // 不显示区间横轴
};
}
this.chartInstance.setOption(option);
}catch(error)
{
console.log('错误')
}
},
clearchart() {
// 清空图表容器
if (this.hasUpperContent )
this.chartInstance.dispose();
this.hasUpperContent = false;
// 在这里可以清理之前的图表实例或其他操作
this.item=[],
this.records=[],
this.inputStr=[],
this.Rdata= [] // 示例数据,可以替换为实际数据
},
handledata(){
if (!this.mytable || this.mytable.length === 0) {
alert("没有数据");
} else {
// 检查是否有选定的列名
if (!this.srow) {
alert("请选择列名");
return null;
} else {
this.inputStr = this.mytable.map(row => {
// 检查 row 是否存在以及选定的列是否存在
if (row && row[this.srow] !== undefined) {
return row[this.srow];
} else {
// 如果选定的列不存在,返回一个默认值或者处理错误
return null; // 你可以根据需要更改此处的行为
}
});
this.dates=this.inputStr;
// 输出提取的列数据
this.Rdata=this.inputStr;
this.xz=this.inputStr;
}
if (!this.srow2) {
return null;
} else {
this.inputStr = this.mytable.map(row => {
// 检查 row 是否存在以及选定的列是否存在
if (row && row[this.srow] !== undefined) {
return row[this.srow];
} else {
// 如果选定的列不存在,返回一个默认值或者处理错误
return null; // 你可以根据需要更改此处的行为
}
});
this.yz=this.inputStr;
// 输出提取的列数据
}
}
},
handletwodata() {
if (!this.mytable || this.mytable.length === 0) {
alert("没有数据");
} else {
if (!this.srow || !this.srow2) {
return null;
} else {
const combinedData = this.mytable.map(row => {
if (row && row[this.srow] !== undefined) {
return [row[this.srow], row[this.srow2]];
} else {
return [null, null]; // 如果选定的属性不存在,返回默认值或者处理错误
}
});
this.records = combinedData;
this.item = combinedData;
console.log(combinedData);
}
}
},
handleGenerateChart() {
this.clearchart();
console.log(this.columns)
try{
this.handledata();
this.handletwodata();
} catch(error) {
alert("请选择数据")
}
if (this.selectedEntity === 'entity1') {
// Count occurrences of each month-year combination
if (!this.gap || !this.srow || !this.stype) {
console.log(this.gap,this.srow , this.stype);
alert("请选择实体、列名或者类型");
return;
}
const counts= this.countMonth()
setTimeout(()=>this.drawChart(counts),500);
} else if (this.selectedEntity=='entity2'){
const counts=this.calculateMonthlyRecords();
console.log(counts);
setTimeout(()=>this.drawChart(counts),500);
} else if (this.selectedEntity=='entity3'){
const counts=this.countDataByInterval();
setTimeout(()=>this.drawChart(counts),500);
}else if(this.selectedEntity=='entity4'){
if (this.srow2!='entity'){
const counts=this.countsumbystring();
setTimeout(()=>this.drawChart(counts),500);
} else {
const counts=this.countStrings();
setTimeout(()=>this.drawChart(counts),500);
}
}
else if (this.selectedEntity=='entity5'){
this.hasUpperContent = true;
const counts={}
for (let i = 0; i < this.xz.length; i++) {
counts[this.xz[i]] = this.yz[i];
}
setTimeout(()=>this.drawChart(counts),500);}
else {
this.$message.warning('请选择实体');
}
}
}
};
</script>
<style scoped>
.container {
display: grid;
grid-template-columns: 35% 65%;
width: 100%;
height: 80vh;
gap: 10px;
text-align: center
}
.left-grid, .right-grid {
background-color: #f0f0f0;
border-radius: 2%;
padding: 20px;
height: 100%;
box-sizing: border-box;
}
.right-grid {
display: grid;
grid-template-rows: 600px auto; /* 上半部分固定为600px下半部分自动填充 */
background-color: #e9d7df;
}
.upper-right {
/* 上半部分样式 */
display: flex;
justify-content: center;
align-items: center;
/* 如果内容溢出,隐藏溢出部分 */
}
.lower-right {
/* 下半部分样式 */
display: flex;
justify-content: center;
align-items: center;
overflow-y: auto; /* 如果内容过多,显示滚动条 */
}
.chart-container {
width: 90%;
height: 90%;
text-align: center;
}
.el-row {
margin-top: 5px;
margin-bottom: 10px;
}
.demo-select {
display: flex;
width: 100%;
padding: 0;
flex-wrap: wrap;
}
.demo-select .block {
padding: 10px 0;
text-align: center;
border-right: solid 1px var(--el-border-color);
flex: 1;
}
.demo-select .block:last-child {
border-right: none;
}
.demo-select .demonstration {
display: block;
color: var(--el-text-color-secondary);
font-size: 14px;
margin-bottom: 20px;
}
.containerHead{
padding:0;
height:8%;
padding :0;
width: 100%;
display:flex;
justify-content: space-between;
background-color: white;
align-items: center;
}
.HeaderPage{
width: 90%;
}
.btnReturnHomePage{
font-size: large;
width: 3%;
font-weight: 25px;
}
</style>