|
|
@@ -1,5 +1,5 @@
|
|
|
<template>
|
|
|
- <div class="content">
|
|
|
+ <div class="content" v-loading="loading">
|
|
|
<el-tabs
|
|
|
ref="tabs"
|
|
|
tab-position="left"
|
|
|
@@ -19,7 +19,7 @@
|
|
|
:before-upload="checkFileType"
|
|
|
:show-file-list="false"
|
|
|
>
|
|
|
- <div class="uploadBoxContent">
|
|
|
+ <div class="uploadBoxContent" inert>
|
|
|
<svg-icon
|
|
|
icon-class="table(2)"
|
|
|
style="width: 40px; height: 40px; margin-right: 10px"
|
|
|
@@ -87,7 +87,7 @@
|
|
|
<DataTable ref="dataTableRef"></DataTable>
|
|
|
</el-tab-pane>
|
|
|
<el-tab-pane name="compute">
|
|
|
- <span slot="label" class="iconFont" @click.stop="dialogVisible = true">
|
|
|
+ <span slot="label" class="iconFont" @click.stop="handleUploadBox">
|
|
|
<el-tooltip
|
|
|
class="item"
|
|
|
effect="dark"
|
|
|
@@ -137,21 +137,31 @@
|
|
|
class="demo-ruleForm"
|
|
|
>
|
|
|
<el-form-item label="选择数据列表:" prop="region">
|
|
|
- <el-select
|
|
|
+ <el-cascader
|
|
|
+ v-model="ruleForm.region"
|
|
|
+ size="small"
|
|
|
+ placeholder="试试搜索:"
|
|
|
+ collapse-tags
|
|
|
+ :options="options"
|
|
|
+ filterable
|
|
|
+ >
|
|
|
+ <!-- :props="{ multiple: true }" -->
|
|
|
+ </el-cascader>
|
|
|
+ <!-- <el-select
|
|
|
v-model="ruleForm.region"
|
|
|
placeholder="请选择活动区域"
|
|
|
size="small"
|
|
|
>
|
|
|
<el-option label="区域一" value="shanghai"></el-option>
|
|
|
<el-option label="区域二" value="beijing"></el-option>
|
|
|
- </el-select>
|
|
|
+ </el-select> -->
|
|
|
</el-form-item>
|
|
|
<el-form-item label="选择数据范围:">
|
|
|
<div class="demo-input-suffix">
|
|
|
<el-input
|
|
|
size="small"
|
|
|
type="number"
|
|
|
- placeholder="最小值"
|
|
|
+ placeholder="开始行"
|
|
|
v-model="ruleForm.min"
|
|
|
>
|
|
|
</el-input>
|
|
|
@@ -159,7 +169,7 @@
|
|
|
<el-input
|
|
|
size="small"
|
|
|
type="number"
|
|
|
- placeholder="最大值"
|
|
|
+ placeholder="结束行"
|
|
|
v-model="ruleForm.max"
|
|
|
>
|
|
|
</el-input>
|
|
|
@@ -167,24 +177,23 @@
|
|
|
</el-form-item>
|
|
|
<el-form-item label="选择特征值计算:" prop="type">
|
|
|
<el-checkbox-group v-model="ruleForm.type">
|
|
|
- <el-checkbox label="有效值" name="type"></el-checkbox>
|
|
|
- <el-checkbox label="平均值" name="type"></el-checkbox>
|
|
|
- <el-checkbox label="最大值" name="type"></el-checkbox>
|
|
|
- <el-checkbox label="最小值" name="type"></el-checkbox>
|
|
|
- <el-checkbox label="峰值" name="type"></el-checkbox>
|
|
|
- <el-checkbox label="峰峰值" name="type"></el-checkbox>
|
|
|
- <el-checkbox label="峰值指标" name="type"></el-checkbox>
|
|
|
- <el-checkbox label="峰度指标" name="type"></el-checkbox>
|
|
|
- <el-checkbox label="歪度指标" name="type"></el-checkbox>
|
|
|
- <el-checkbox label="裕度指标" name="type"></el-checkbox>
|
|
|
- <el-checkbox label="脉冲指标" name="type"></el-checkbox>
|
|
|
- <el-checkbox label="波形指标" name="type"></el-checkbox>
|
|
|
+ <el-checkbox label="有效值" name="Xrms"></el-checkbox>
|
|
|
+ <el-checkbox label="平均值" name="Mean"></el-checkbox>
|
|
|
+ <el-checkbox label="最大值" name="Max"></el-checkbox>
|
|
|
+ <el-checkbox label="最小值" name="Min"></el-checkbox>
|
|
|
+ <el-checkbox label="峰值" name="Xp"></el-checkbox>
|
|
|
+ <el-checkbox label="峰峰值" name="Xpp"></el-checkbox>
|
|
|
+ <el-checkbox label="峰度指标" name="Cf"></el-checkbox>
|
|
|
+ <el-checkbox label="歪度指标" name="Sk"></el-checkbox>
|
|
|
+ <el-checkbox label="裕度指标" name="Ce"></el-checkbox>
|
|
|
+ <el-checkbox label="脉冲指标" name="If"></el-checkbox>
|
|
|
+ <el-checkbox label="波形指标" name="Sf"></el-checkbox>
|
|
|
</el-checkbox-group>
|
|
|
</el-form-item>
|
|
|
</el-form>
|
|
|
<span slot="footer" class="dialog-footer">
|
|
|
- <el-button @click="dialogVisible = false">取 消</el-button>
|
|
|
- <el-button type="primary" @click="dialogVisible = false"
|
|
|
+ <el-button @click="resetForm">取 消</el-button>
|
|
|
+ <el-button type="primary" @click="submitComputedFn('ruleForm')"
|
|
|
>确 定</el-button
|
|
|
>
|
|
|
</span>
|
|
|
@@ -203,9 +212,10 @@ import DragChart from "./components/custonAsCom/dragChart/index.vue";
|
|
|
import AssociatedFields from "./components/custonAsCom/AssociatedFields.vue";
|
|
|
import Papa from "papaparse";
|
|
|
import * as XLSX from "xlsx";
|
|
|
-import { storeSetData } from "@/utils/indexedDb";
|
|
|
+import { storeSetData, getDataFromIndexedDB } from "@/utils/indexedDb";
|
|
|
import { format } from "date-fns";
|
|
|
import { mapMutations, mapState } from "vuex";
|
|
|
+import axios from "axios";
|
|
|
export default {
|
|
|
components: {
|
|
|
DataTable,
|
|
|
@@ -215,6 +225,8 @@ export default {
|
|
|
},
|
|
|
data() {
|
|
|
return {
|
|
|
+ options: [],
|
|
|
+ loading: false,
|
|
|
db: null,
|
|
|
activeName: "chart",
|
|
|
showDatabaseTable: false,
|
|
|
@@ -249,6 +261,22 @@ export default {
|
|
|
...mapState("dragChart", {
|
|
|
updateTriggerGetData: "updateTriggerGetData",
|
|
|
}),
|
|
|
+ selectedNames() {
|
|
|
+ const nameMap = {
|
|
|
+ 有效值: "Xrms",
|
|
|
+ 平均值: "Mean",
|
|
|
+ 最大值: "Max",
|
|
|
+ 最小值: "Min",
|
|
|
+ 峰值: "Xp",
|
|
|
+ 峰峰值: "Xpp",
|
|
|
+ 峰度指标: "Cf",
|
|
|
+ 歪度指标: "Sk",
|
|
|
+ 裕度指标: "Ce",
|
|
|
+ 脉冲指标: "If",
|
|
|
+ 波形指标: "Sf",
|
|
|
+ };
|
|
|
+ return this.ruleForm.type.map((label) => nameMap[label]);
|
|
|
+ },
|
|
|
},
|
|
|
watch: {
|
|
|
updateTriggerGetData: function (newVal) {
|
|
|
@@ -265,6 +293,7 @@ export default {
|
|
|
"setTriggerGetData",
|
|
|
"setUpdateTriggerGetData",
|
|
|
]),
|
|
|
+
|
|
|
async initDB() {
|
|
|
return new Promise((resolve, reject) => {
|
|
|
const request = indexedDB.open("FileDataDB", 2); // 使用较高版本
|
|
|
@@ -277,7 +306,7 @@ export default {
|
|
|
db.createObjectStore("files", { keyPath: "id" });
|
|
|
}
|
|
|
};
|
|
|
- request.onsuccess = (event) => {
|
|
|
+ request.onsuccess = async (event) => {
|
|
|
this.db = event.target.result;
|
|
|
console.log("数据库已成功初始化。");
|
|
|
resolve();
|
|
|
@@ -288,6 +317,164 @@ export default {
|
|
|
};
|
|
|
});
|
|
|
},
|
|
|
+ async handleUploadBox() {
|
|
|
+ this.dialogVisible = true;
|
|
|
+ const indexeddbData = await getDataFromIndexedDB();
|
|
|
+ this.options = indexeddbData.map((item) => {
|
|
|
+ return {
|
|
|
+ value: item.fileId,
|
|
|
+ label: item.filename,
|
|
|
+ children: Object.keys(item.fileData[0]).map((val) => ({
|
|
|
+ value: val,
|
|
|
+ label: val,
|
|
|
+ })),
|
|
|
+ };
|
|
|
+ });
|
|
|
+ console.log(this.options, "调用数据");
|
|
|
+ },
|
|
|
+ async submitComputedFn(formName) {
|
|
|
+ try {
|
|
|
+ // 1. 验证表单
|
|
|
+ if (!(await this.validateForm(formName))) return;
|
|
|
+ if (Number(this.ruleForm.max) < Number(this.ruleForm.min)) {
|
|
|
+ this.$message.error("开始行不可以大于结束行");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ // 2. 获取 IndexedDB 数据
|
|
|
+ const indexeddbData = await getDataFromIndexedDB();
|
|
|
+ const region = this.getRegionData(indexeddbData);
|
|
|
+
|
|
|
+ if (!region.length) {
|
|
|
+ console.warn("当前选择的列未找到数据");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 3. 调用算法接口
|
|
|
+ const resData = await this.fetchAlgorithmData(region[0]);
|
|
|
+
|
|
|
+ // 4. 筛选和处理数据
|
|
|
+ const filteredData = this.filterResponseData(resData);
|
|
|
+
|
|
|
+ // 5. 构建导出数据
|
|
|
+ const resObj = this.buildExportData(indexeddbData, filteredData);
|
|
|
+ this.storeData(resObj);
|
|
|
+ this.resetForm();
|
|
|
+ console.log(resObj, "resObj");
|
|
|
+ } catch (error) {
|
|
|
+ console.error("提交过程中发生错误:", error);
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ async validateForm(formName) {
|
|
|
+ try {
|
|
|
+ const valid = await this.$refs[formName].validate();
|
|
|
+ if (!valid) {
|
|
|
+ console.warn("表单验证失败");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ } catch (error) {
|
|
|
+ console.error("表单验证错误:", error);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ },
|
|
|
+ //生成数据
|
|
|
+ getRegionData(indexeddbData) {
|
|
|
+ return indexeddbData
|
|
|
+ .filter((item) => item.fileId === this.ruleForm.region[0])
|
|
|
+ .map((item) =>
|
|
|
+ item.fileData.map((val, ind) => ({
|
|
|
+ index: ind + 1,
|
|
|
+ value: val[this.ruleForm.region[1]],
|
|
|
+ }))
|
|
|
+ );
|
|
|
+ },
|
|
|
+ //调用算法接口
|
|
|
+ async fetchAlgorithmData(regionData) {
|
|
|
+ try {
|
|
|
+ const res = await axios.post("/sAlgorithm/CalculateFeatures/", {
|
|
|
+ data: regionData,
|
|
|
+ start_index: Number(this.ruleForm.min),
|
|
|
+ end_index: Number(this.ruleForm.max),
|
|
|
+ });
|
|
|
+ return JSON.parse(res.data, "res");
|
|
|
+ } catch (error) {
|
|
|
+ console.error("算法接口调用失败:", error);
|
|
|
+ throw error;
|
|
|
+ }
|
|
|
+ },
|
|
|
+ //过滤字段
|
|
|
+ filterResponseData(resData) {
|
|
|
+ return resData.map((item) => {
|
|
|
+ const filteredItem = { ...item };
|
|
|
+ Object.keys(filteredItem).forEach((key) => {
|
|
|
+ if (
|
|
|
+ this.selectedNames.length > 0 &&
|
|
|
+ !this.selectedNames.includes(key) &&
|
|
|
+ key !== "index" &&
|
|
|
+ key !== "value"
|
|
|
+ ) {
|
|
|
+ delete filteredItem[key];
|
|
|
+ }
|
|
|
+ });
|
|
|
+ return filteredItem;
|
|
|
+ });
|
|
|
+ },
|
|
|
+ //处理算法返回的数据
|
|
|
+ buildExportData(indexeddbData, resData) {
|
|
|
+ const nameMap = {
|
|
|
+ 有效值: "Xrms",
|
|
|
+ 平均值: "Mean",
|
|
|
+ 最大值: "Max",
|
|
|
+ 最小值: "Min",
|
|
|
+ 峰值: "Xp",
|
|
|
+ 峰峰值: "Xpp",
|
|
|
+ 峰度指标: "Cf",
|
|
|
+ 歪度指标: "Sk",
|
|
|
+ 裕度指标: "Ce",
|
|
|
+ 脉冲指标: "If",
|
|
|
+ 波形指标: "Sf",
|
|
|
+ };
|
|
|
+ const resObj = indexeddbData.find(
|
|
|
+ (item) => item.fileId === this.ruleForm.region[0]
|
|
|
+ );
|
|
|
+ if (!resObj) {
|
|
|
+ console.warn("未找到对应文件数据");
|
|
|
+ return {};
|
|
|
+ }
|
|
|
+ resObj.filename =
|
|
|
+ format(new Date(), "yyyyMMdd-HH:mm:ss") + resObj.fileOldName;
|
|
|
+ resObj.fileId = new Date().getTime();
|
|
|
+ resObj.fileData = resData.map((item) => {
|
|
|
+ const dynamicKeys = this.ruleForm.type.reduce((acc, label) => {
|
|
|
+ const fieldName = this.selectedNames.find(
|
|
|
+ (name) => nameMap[label] === name
|
|
|
+ );
|
|
|
+ if (fieldName) {
|
|
|
+ acc[label] = item[fieldName];
|
|
|
+ }
|
|
|
+ return acc;
|
|
|
+ }, {});
|
|
|
+
|
|
|
+ return {
|
|
|
+ [this.ruleForm.region[1]]: item.value,
|
|
|
+ ...dynamicKeys,
|
|
|
+ };
|
|
|
+ });
|
|
|
+
|
|
|
+ return resObj;
|
|
|
+ },
|
|
|
+
|
|
|
+ resetForm() {
|
|
|
+ this.ruleForm = {
|
|
|
+ max: "",
|
|
|
+ min: "",
|
|
|
+ region: [],
|
|
|
+ type: [],
|
|
|
+ };
|
|
|
+ this.dialogVisible = false; // 重置表单状态
|
|
|
+ },
|
|
|
+
|
|
|
async storeData(newFileData) {
|
|
|
await storeSetData(this.db, "files", "fileDataArray", newFileData, () => {
|
|
|
this.setTriggerGetData(true);
|
|
|
@@ -335,10 +522,12 @@ export default {
|
|
|
};
|
|
|
if (results.data.length > 0) {
|
|
|
this.storeData(fileData);
|
|
|
+ this.loading = false;
|
|
|
}
|
|
|
},
|
|
|
error: (error) => {
|
|
|
console.error("Error parsing CSV:", error);
|
|
|
+ this.loading = false;
|
|
|
},
|
|
|
});
|
|
|
} else {
|
|
|
@@ -358,6 +547,7 @@ export default {
|
|
|
};
|
|
|
if (sheetData.length > 0) {
|
|
|
this.storeData(fileData);
|
|
|
+ this.loading = false;
|
|
|
}
|
|
|
// console.log("Parsed Excel Sheet Data:", sheetData);
|
|
|
// 可以进一步处理解析后的数据
|
|
|
@@ -376,8 +566,16 @@ export default {
|
|
|
file.name.endsWith(".xlsx");
|
|
|
if (!isPdf) {
|
|
|
this.$message.error("只能上传csv文件或xlsx文件");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ // 判断文件大小(以字节为单位,100kB = 102400字节)
|
|
|
+ const maxSize = 50 * 1024; // 100kB
|
|
|
+ if (file.size > maxSize) {
|
|
|
+ this.$message.error("文件大小不能超过50kB");
|
|
|
+ return false;
|
|
|
}
|
|
|
- return isPdf;
|
|
|
+ this.loading = true;
|
|
|
+ return true;
|
|
|
},
|
|
|
},
|
|
|
async mounted() {
|