front/src/views/CluesPage.vue

445 lines
16 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-container style="height:100%">
<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-main class ='container_Tools_Main'>
<!-- 折叠版存放约束条件显示 -->
<el-container class = 'containerConstraints'>
<el-collapse v-model = 'activeNames'>
<el-collapse-item name = '1'>
<div class = 'divConstraintView' v-for="(i,index) in Constraints" :key="index">
{{"逻辑关系:" + i.merge + " 约束列:" + search_clu_name(i.col_id) + " " +Condition_to_string(i)}}
<button @click="constraint_delete(index)">删除</button>
</div>
</el-collapse-item>
</el-collapse>
</el-container>
<!-- 工具栏 -->
<el-header class ='containerTools'>
<el-button class = 'btnDelete'>
<el-tooltip content = '删除所有'>
<el-icon><Delete /></el-icon>
</el-tooltip>
</el-button>
<el-button class = 'btnSearch' @click = 'searchDialogVisible = true'>
<el-tooltip content = '条件查找'>
<el-icon><Search /></el-icon>
</el-tooltip>
<!-- 条件查找对应的对话框 -->
<!-- @author myz
@brief: 自实现的对话框用于提交约束条件添加
@params: colDate 表头属性的数据
@v-model:isVisible 控制对话框可见的v-model
@confirm: @confirm 处理子部件的confirm事件 -->
<ConstraintSearchDialog
:colData = 'clueCols'
v-model:isVisible = 'searchDialogVisible'
@confirm = 'handleSearchDialogConfirm'
/>
</el-button>
<el-button class = 'btnMore' @click="dochart">
<el-tooltip content = '更多'>
<el-icon><More /></el-icon>
</el-tooltip>
</el-button>
</el-header>
<EditDialog :columns="cols" ref="editDialog" :editDataID="currentEditDataID"></EditDialog>
<el-main class = 'containerMain'>
<el-table
class = 'containerTable'
:data="formattedTableData"
height="100%"
style="width: 100%"
@selection-change="handleSelectionChange"
>
<el-table-column type="selection" width="55" style="background-color: black;"/>
<el-table-column class = 'containerTabHead'
v-for="(column, index) in cols"
:key="index"
:prop="column.prop"
:label="column.label"
/>
<el-table-column fixed="right" width = 150px label="操作">
<template #header>
<div style="display: flex; justify-self: flex-end; padding-left: 38px;">操作</div>
</template>
<template #default="scope">
<!-- 使用插槽将数据传入到方法watchClue中 -->
<el-button class = 'btnItemEdit' size="small" @click="editClue(scope.row)">编辑</el-button>
<el-button class = 'btnItemDelete' size="small" @click="deleteClue(scope.row)"> 删除 </el-button>
</template>
</el-table-column>
</el-table>
</el-main>
<!-- </el-main> -->
</el-main>
</el-container>
</template>
<script>
const activeNames = ref(['1']);
// 解决刷新率问题
const debounce = (fn, delay) => {
let timer;
return (...args) => {
if (timer) {
clearTimeout(timer)
}
timer = setTimeout(() => {
fn(...args)
}, delay)
}
};
// 解决刷新率问题
const _ResizeObserver = window.ResizeObserver;
window.ResizeObserver = class ResizeObserver extends _ResizeObserver{
constructor(callback) {
callback = debounce(callback, 200);
super(callback);
}
};
import ConstraintSearchDialog from "@/components/components_cluespage/ConstraintSearchDialog.vue"
import EditDialog from "@/components/components_cluespage/EditDialog.vue"
import HeaderPage from "@/views/HeaderPage.vue"
import {ref} from 'vue'
export default{
components:{
ConstraintSearchDialog,
HeaderPage,
EditDialog,
},
name:'CluesPage',
data(){
// 接收传入的id
const clueId = this.$route.params.id;
const pageTitle = this.$route.params.pageTitle;
// console.log("接收到的线索库ID", clueId)
const generateMockData = (cols, numRows = 20) => {
const data = [];
for (let i = 0; i < numRows; i++) {
const row = { col_id: (i + 1).toString() };
cols.forEach((col, index) => {
row[`col_${index + 1}`] = `data_${i + 1}_${index + 1}`;
});
data.push(row);
}
return data;
};
const clueCols = generateColumns(4); // 生成包含10列的列定义数组, 实际运行时可能需要注释掉防止与data中的冲突
// 生成10列的列定义数组
function generateColumns(numCols) {
const columns = [];
for (let i = 1; i <= numCols; i++) {
columns.push({ col_id: `${i}`, col_name: `Column ${i}` });
}
return columns;
}
return {
// 用于查找功能对话框的变量
searchDialogVisible : false,
// 查找所用变量
"Constraints":[// 注意 用的是复数形式
{"merge":"AND","col_id":"3","type":"double","down":"0","up":"INF","inside":"","date":""}, // 满足第1_3列实数范围为大于等于0的
{"merge":"AND","col_id":"2","type":"date","down":"","up":"","inside":"","date":"03.06.2024,30.06.2024"}, // 同时满足第!_2列日期早于2024/1/1的
{"merge":"OR","col_id":"4","type":"string","down":"","up":"","inside":"AAA","date":""} // 或者满足第1_4列(字符串),存在“AAA”这个连续字串的
],
// 显示当前页面的名称
pageTitle,
clueId,
chart:false,
currentEditDataID: {},
selectedColumnData :{},
clueCols, // 这个实际运行时可能要改为 clueCols[]
clueData: generateMockData(clueCols, 20), // 生成 20 行数据, 实际运行时clueData:[]
}
},
methods:{
// 处理子部件的confirm事件
handleSearchDialogConfirm(form){
console.log("提交约束条件", form);
const newConstraint = {
"merge": form.logic,
"col_id": form.col_id,
"type": form.type,
"inside": form.search_string,
"up": form.max_limit,
"down": form.min_limit,
"date": form.continuous_time[0] + ',' + form.continuous_time[1],
}
this.Constraints.push(newConstraint);
},
// 根据属性id显示属性
search_clu_name(aa){
for (let col of this.clueCols) {
if(aa == col.col_id)
return col.col_name;
}
},
Condition_to_string(Constraint){
if(Constraint.type == "string"){
return " 包含 " + Constraint.inside;
}
if(Constraint.up == "INF" && Constraint.down == "INF"){
return " 类型为 " + Constraint.type;
}
if(Constraint.up == "INF" && Constraint.type == "double"){
return " 大于等于 " + Constraint.down;
}
if(Constraint.down == "INF" && Constraint.type == "double"){
return " 小于等于 " + Constraint.up;
}
if(Constraint.type == "double")return " 在 " + Constraint.down + " 和 " + Constraint.up + "之间";
if(Constraint.type == "date")return "在 " + Constraint.date + "之间";
},
constraint_delete(index){
this.Constraints.splice(index, 1);
},
dochart(){
const table=JSON.stringify(this.clueData);
const column=JSON.stringify(this.cols);
this.$router.push({name:'Graph',params:{columns:column,tabledata:table}})
},
handleSelectionChange(selection) {
// 在这里处理选择变化selection 是选中的行数据数组
this.selectedColumnData = selection;
console.log( this.selectedColumnData);
console.log('选择的行数据:', selection);
},
receiveSrow(value) {
// 在这里处理传递过来的值
this.srow = value;
console.log("djlasj",value);
},
// 返回首页的动态路由
returnHome(){
this.$router.push({name:'Table'})
},
// 获取所有列名
getClueCols(){
this.$axios.post('http://localhost:8000/showClueCol/', {table_id:this.clueId}).then(response=>{
this.clueCols = response.data;
})
},
// 获取某一线索库数据
getClueData(){
this.$axios.post('http://localhost:8000/showClue/',{table_id:this.clueId}).then(response=>{
this.clueData = response.data;
})
},
mergeCols(){
// 创建一个映射表,便于查找列名
const colMap = this.clueCols.reduce((acc, col) => {
acc[col.col_id] = col.col_name;
return acc;
}, {});
// 遍历clueData的第一个元素构造新数组
// 注意:这里假设所有对象的结构一致,且至少有一个元素
const mergedColumns = Object.keys(this.clueData[0]).map(key => {
if (key.startsWith('col_')) {
const colId = key.replace('col_', ''); // 提取数字部分
if(colId != 'id'){//排除id列
return { prop: key, label: colMap[colId] || '未知列名' };
}
}
return null; // 或者忽略非col_开头的键
}).filter(Boolean); // 过滤掉null值
// 检查合并后的结果
// console.log('合并之后的表头:',mergedColumns);
return mergedColumns;
},
deleteClue(row){
const postData = {
table_id:this.clueId,
clue_id:row.clue_id
};
//console.log(row)
this.$axios.post('http://localhost:8000/delClue/',postData).then(response=>{
const message = response.data.message;
// 根据返回消息,进行不同的操作
if(message == "删除成功"){
// 调用this.$message组件进行弹窗提示
this.$message({
type:'success',
message:'删除成功!'
});
// 刷新页面
location.reload();
}else if(message == "删除失败"){
this.$message({
type:'error',
message:'删除失败,请重试!'
});
}
})
.catch(error=>{
// 使用自定义的错误处理
this.$handleNetError(error);
});
},
// 编辑线索记录按钮
editClue(row){
let editDataID = {
table_id:this.clueId,
clue_id:row.col_id
};
this.$refs.editDialog.dialogVisible = true; // 对话框是否可见
this.$refs.editDialog.formData = this.formatFormData(row); // 表单数据
this.currentEditDataID = editDataID;
console.log(editDataID);
},
// 将数据格式化成表单数据
formatFormData(row) {
const formData = {};
this.cols.forEach(col => {
if (col.prop !== 'id') {
formData[col.prop] = row[col.prop];
}
});
return formData;
},
},
computed: {
cols(){
if (this.clueCols.length && this.clueData.length) {
// console.log('cols: ', this.mergeCols());
return this.mergeCols();
}
return []; // 或者返回一个空数组,直到数据加载完成
},
formattedTableData() {
// 保留原始ID同时格式化其他数据以匹配动态表头
const Data = this.clueData.map(row => {
const newRow = { ...row }; // 复制row以避免修改原始数据
// 根据动态列,重新组织数据对象
this.cols.forEach(col => {
if (col.label !== 'ID') {
newRow[col.label] = newRow[col.prop];
// console.log('newRow',newRow)
// delete newRow[col.label]; // 如果需要可以删除原始格式的属性按照label会去掉id
}
});
// console.log('newRow: ', newRow)
return newRow;
});
// console.log('展示的数据:', Data);
// console.log('Data.col_id:', Data[0].col_id);
return Data;
}
},
watch: {
// 调试约束条件添加的方法
searchDialogVisible(newValue){
console.log(newValue);
},
Constraints(newv,oldv){
console.log(newv);
},
},
//加载页面的时候获取数据
beforeMount() {
// this.getClueCols();
// this.getClueData();
}
};
</script>
<style scoped>
.el-container{
padding: 0;
}
.containerTools{
height:6%;
padding:2%;
display:flex;
justify-content: flex-end;
align-items: center;
}
.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;
}
.container_Tools_Main{
padding:0;
background-color: #f5f6fa;
height: 92%;
width: 100%;
}
.el-button{
background-color: transparent;
margin:2;
padding:2;
border: 0;
color: #0e5858;
font-size: 24px;
}
.el-button:hover{
background-color: rgba(255, 255, 255, 0.7);
}
/* 设置表格 */
.containerMain{
background-color: #f5f6fa;
padding: 10px;
padding-top: 0;
height:90%;
overflow: auto;
}
.btnItemDelete{
background-color: lightcoral;
color: white;
border-radius: 14px;
font-size: 12px;
font-weight: bold;
}
.btnItemDelete:hover{
background: rgba(240, 128, 128, 0.647);
}
.btnItemEdit{
background-color: #1DAFAF;
color: white;
border-radius: 14px;
font-size: 12px;
font-weight: bold;
}
.btnItemEdit:hover{
background: #1dafafd2;
}
.btnDelete,.btnSearch,.btnMore{
text-align: start;
padding: 0.6%;
margin: 0;
}
</style>