|
|
@@ -1,575 +0,0 @@
|
|
|
-<template>
|
|
|
- <div class="global-variable">
|
|
|
- <!-- tab 切换 -->
|
|
|
- <el-tabs v-model="activeName" @tab-click="handleClick">
|
|
|
- <el-tab-pane
|
|
|
- v-for="item in menuItems"
|
|
|
- :key="item.component"
|
|
|
- :label="item.name"
|
|
|
- :name="item.component"
|
|
|
- />
|
|
|
- </el-tabs>
|
|
|
-
|
|
|
- <!-- 查询条件 -->
|
|
|
- <div class="searchbox">
|
|
|
- <p>
|
|
|
- 单位:
|
|
|
- <selecttree
|
|
|
- size="small"
|
|
|
- style="width: 180px"
|
|
|
- placeholder="请选择所属公司"
|
|
|
- :list="tabConditions[activeTab].parentOpt"
|
|
|
- type="1"
|
|
|
- v-model="tabConditions[activeTab].companyCode"
|
|
|
- @change="parentChange"
|
|
|
- :defaultParentProps="{
|
|
|
- children: 'children',
|
|
|
- label: 'companyName',
|
|
|
- value: 'codeNumber',
|
|
|
- }"
|
|
|
- />
|
|
|
- </p>
|
|
|
- <p>
|
|
|
- 风机:
|
|
|
- <el-select
|
|
|
- size="small"
|
|
|
- style="width: 150px"
|
|
|
- v-model="tabConditions[activeTab].unitvalue"
|
|
|
- @change="getchedian"
|
|
|
- placeholder="请选择"
|
|
|
- >
|
|
|
- <el-option
|
|
|
- v-for="item in tabConditions[activeTab].unitoptions"
|
|
|
- :key="item.engineCode"
|
|
|
- :label="item.engineName"
|
|
|
- :value="item.engineCode"
|
|
|
- />
|
|
|
- </el-select>
|
|
|
- </p>
|
|
|
- <p>
|
|
|
- 测点:
|
|
|
- <el-select
|
|
|
- v-model="tabConditions[activeTab].monitoringvalue"
|
|
|
- size="small"
|
|
|
- clearable
|
|
|
- placeholder="请选择"
|
|
|
- :disabled="activeTab === 'Temperature'"
|
|
|
- >
|
|
|
- <el-option
|
|
|
- v-for="item in tabConditions[activeTab].monitoringoptions"
|
|
|
- :key="item.itemKey"
|
|
|
- :label="item.itemValue"
|
|
|
- :value="item.itemKey"
|
|
|
- />
|
|
|
- </el-select>
|
|
|
- </p>
|
|
|
-
|
|
|
- <p>
|
|
|
- 采样频率:
|
|
|
- <el-select
|
|
|
- v-model="tabConditions[activeTab].frequencyvalue"
|
|
|
- size="small"
|
|
|
- clearable
|
|
|
- placeholder="请选择"
|
|
|
- :disabled="activeTab === 'Temperature'"
|
|
|
- >
|
|
|
- <el-option
|
|
|
- v-for="item in tabConditions[activeTab].frequencyoptions"
|
|
|
- :key="item"
|
|
|
- :label="item"
|
|
|
- :value="item"
|
|
|
- />
|
|
|
- </el-select>
|
|
|
- </p>
|
|
|
- <p>
|
|
|
- 时间:
|
|
|
- <el-date-picker
|
|
|
- size="small"
|
|
|
- v-model="tabConditions[activeTab].timevalue"
|
|
|
- type="datetimerange"
|
|
|
- range-separator="至"
|
|
|
- start-placeholder="开始日期"
|
|
|
- end-placeholder="结束日期"
|
|
|
- />
|
|
|
- <!-- :picker-options="datePickerOptions" -->
|
|
|
- </p>
|
|
|
- <el-button
|
|
|
- type="primary"
|
|
|
- size="small"
|
|
|
- @click="onSearchClick"
|
|
|
- class="search-btn"
|
|
|
- >查询</el-button
|
|
|
- >
|
|
|
- </div>
|
|
|
-
|
|
|
- <!-- 动态组件内容 -->
|
|
|
- <div class="main-body">
|
|
|
- <keep-alive>
|
|
|
- <component
|
|
|
- ref="activeComponent"
|
|
|
- :is="activeTab"
|
|
|
- :codedata="tabData[activeTab].codedata"
|
|
|
- v-bind="
|
|
|
- activeTab === 'Temperature'
|
|
|
- ? { echartsdata: tabData.Temperature.echartsdata }
|
|
|
- : {}
|
|
|
- "
|
|
|
- :totalCount="tabData[activeTab].totalCount"
|
|
|
- :totalPage="tabData[activeTab].totalPage"
|
|
|
- :fieldCode="tabConditions[activeTab].companyCode"
|
|
|
- :windTurbineNumber="tabConditions[activeTab].unitvalue"
|
|
|
- @updatePage="handlePageChange"
|
|
|
- />
|
|
|
- </keep-alive>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
-</template>
|
|
|
-
|
|
|
-<script>
|
|
|
-import * as FileSaver from "file-saver";
|
|
|
-import * as XLSX from "xlsx";
|
|
|
-import {
|
|
|
- getSysOrganizationAuthTreeByRoleId,
|
|
|
- windEngineGrouPage,
|
|
|
- queryDetectionDic,
|
|
|
-} from "@/api/ledger.js";
|
|
|
-import selecttree from "../../components/selecttree.vue";
|
|
|
-import Bearing from "./components/malfunction/bearing.vue";
|
|
|
-import Dissymmetry from "./components/malfunction/dissymmetry.vue";
|
|
|
-import Gear from "./components/malfunction/gear.vue";
|
|
|
-import Loose from "./components/malfunction/loose.vue";
|
|
|
-import Misalignment from "./components/malfunction/misalignment.vue";
|
|
|
-import Temperature from "./components/malfunction/temperature.vue";
|
|
|
-import axios from "axios";
|
|
|
-
|
|
|
-export default {
|
|
|
- components: {
|
|
|
- selecttree,
|
|
|
- Bearing,
|
|
|
- Dissymmetry,
|
|
|
- Gear,
|
|
|
- Loose,
|
|
|
- Misalignment,
|
|
|
- Temperature,
|
|
|
- },
|
|
|
- data() {
|
|
|
- return {
|
|
|
- activeTab: "Bearing",
|
|
|
- activeName: "Bearing",
|
|
|
- menuItems: [
|
|
|
- {
|
|
|
- name: "轴承诊断",
|
|
|
- icon: require("@/assets/img/ZC.png"),
|
|
|
- component: "Bearing",
|
|
|
- },
|
|
|
- {
|
|
|
- name: "齿轮诊断",
|
|
|
- icon: require("@/assets/img/SZ.png"),
|
|
|
- component: "Gear",
|
|
|
- },
|
|
|
- {
|
|
|
- name: "不对中诊断",
|
|
|
- icon: require("@/assets/img/DZ.png"),
|
|
|
- component: "Dissymmetry",
|
|
|
- },
|
|
|
- {
|
|
|
- name: "不平衡诊断",
|
|
|
- icon: require("@/assets/img/DC.png"),
|
|
|
- component: "Misalignment",
|
|
|
- },
|
|
|
- {
|
|
|
- name: "松动诊断",
|
|
|
- icon: require("@/assets/img/SD.png"),
|
|
|
- component: "Loose",
|
|
|
- },
|
|
|
- {
|
|
|
- name: "温度诊断",
|
|
|
- icon: require("@/assets/img/WD.png"),
|
|
|
- component: "Temperature",
|
|
|
- },
|
|
|
- ],
|
|
|
- tabConditions: {
|
|
|
- Bearing: {},
|
|
|
- Gear: {},
|
|
|
- Dissymmetry: {},
|
|
|
- Misalignment: {},
|
|
|
- Loose: {},
|
|
|
- Temperature: {},
|
|
|
- },
|
|
|
- tabData: {
|
|
|
- Bearing: { codedata: [], totalCount: 0, totalPage: 0 },
|
|
|
- Gear: { codedata: [], totalCount: 0, totalPage: 0 },
|
|
|
- Dissymmetry: { codedata: [], totalCount: 0, totalPage: 0 },
|
|
|
- Misalignment: { codedata: [], totalCount: 0, totalPage: 0 },
|
|
|
- Loose: { codedata: [], totalCount: 0, totalPage: 0 },
|
|
|
- Temperature: {
|
|
|
- codedata: [],
|
|
|
- totalCount: 0,
|
|
|
- totalPage: 0,
|
|
|
- echartsdata: {},
|
|
|
- },
|
|
|
- },
|
|
|
- datePickerOptions: {
|
|
|
- onPick: ({ minDate, maxDate }) => {
|
|
|
- if (minDate && !maxDate) {
|
|
|
- const maxTime = new Date(
|
|
|
- minDate.getTime() + 30 * 24 * 60 * 60 * 1000
|
|
|
- );
|
|
|
- this.datePickerOptions.disabledDate = (time) => {
|
|
|
- return (
|
|
|
- time.getTime() < minDate.getTime() ||
|
|
|
- time.getTime() > maxTime.getTime()
|
|
|
- );
|
|
|
- };
|
|
|
- } else {
|
|
|
- this.datePickerOptions.disabledDate = () => false;
|
|
|
- }
|
|
|
- },
|
|
|
- disabledDate: () => false,
|
|
|
- },
|
|
|
- };
|
|
|
- },
|
|
|
- created() {
|
|
|
- for (const key in this.tabConditions) {
|
|
|
- this.tabConditions[key] = this.defaultCondition();
|
|
|
- }
|
|
|
- this.GETtree();
|
|
|
- },
|
|
|
- methods: {
|
|
|
- defaultCondition() {
|
|
|
- return {
|
|
|
- unitvalue: "",
|
|
|
- unitoptions: [],
|
|
|
- companyCode: "",
|
|
|
- parentOpt: [],
|
|
|
- timevalue: [],
|
|
|
- monitoringvalue: "",
|
|
|
- monitoringoptions: [],
|
|
|
- frequencyvalue: "",
|
|
|
- frequencyoptions: [],
|
|
|
- };
|
|
|
- },
|
|
|
- handleClick(tab) {
|
|
|
- this.activeTab = tab.name;
|
|
|
- },
|
|
|
- async GETtree() {
|
|
|
- const res = await getSysOrganizationAuthTreeByRoleId();
|
|
|
- const treedata = res.data;
|
|
|
- const processed = this.processTreeData(treedata);
|
|
|
-
|
|
|
- for (const key in this.tabConditions) {
|
|
|
- this.tabConditions[key].parentOpt = processed;
|
|
|
- }
|
|
|
- },
|
|
|
- parentChange(data) {
|
|
|
- const condition = this.tabConditions[this.activeTab];
|
|
|
- if (!data?.codeNumber) return;
|
|
|
- condition.unitvalue = "";
|
|
|
- condition.monitoringvalue = "";
|
|
|
- condition.frequencyvalue = "";
|
|
|
-
|
|
|
- windEngineGrouPage({
|
|
|
- fieldCode: data.codeNumber,
|
|
|
- pageNum: 1,
|
|
|
- pageSize: 99,
|
|
|
- }).then((res) => {
|
|
|
- condition.unitoptions = res.data.list;
|
|
|
- });
|
|
|
-
|
|
|
- axios
|
|
|
- .get(`/ETLapi/waveData/getAllSamplingFrequency/${data.codeNumber}`)
|
|
|
-.then((res) => {
|
|
|
- condition.frequencyoptions = (res.data.datas || [])
|
|
|
- .map(item => Number(item))
|
|
|
- .filter(num => num >= 12800)
|
|
|
- .map(num => num.toString());
|
|
|
-});
|
|
|
-
|
|
|
-
|
|
|
- condition.companyCode = data.codeNumber;
|
|
|
- },
|
|
|
- getchedian(value) {
|
|
|
- const condition = this.tabConditions[this.activeTab];
|
|
|
- const companyCode = condition.companyCode;
|
|
|
-
|
|
|
- axios
|
|
|
- .post(`/ETLapi/waveData/getAllMesurePointName/${companyCode}/${value}`)
|
|
|
- .then((res) => {
|
|
|
- condition.monitoringvalue = "";
|
|
|
- if (res.data.code === 500) {
|
|
|
- condition.monitoringoptions = [];
|
|
|
- this.$message({
|
|
|
- message: "当前风场不存在测点和采样频率数据" || "未知错误",
|
|
|
- type: "warning",
|
|
|
- });
|
|
|
- return;
|
|
|
- }
|
|
|
- if (res.data.code === 200) {
|
|
|
- const datas = Array.isArray(res.data.datas) ? res.data.datas : [];
|
|
|
- condition.monitoringoptions = datas;
|
|
|
- if (datas.length === 0) {
|
|
|
- this.$message({ message: "暂无数据", type: "warning" });
|
|
|
- }
|
|
|
- }
|
|
|
- })
|
|
|
- .catch((err) => {
|
|
|
- console.error("测点请求失败:", err);
|
|
|
- condition.monitoringoptions = [];
|
|
|
- });
|
|
|
- },
|
|
|
- processTreeData(treeData) {
|
|
|
- const processedData = [];
|
|
|
- function processNode(node) {
|
|
|
- if (node.codeType === "field") {
|
|
|
- node.companyName = node.fieldName;
|
|
|
- }
|
|
|
- if (node.children && node.children.length > 0) {
|
|
|
- node.children.forEach(processNode);
|
|
|
- }
|
|
|
- }
|
|
|
- treeData.forEach((root) => {
|
|
|
- processNode(root);
|
|
|
- processedData.push(root);
|
|
|
- });
|
|
|
- return processedData;
|
|
|
- },
|
|
|
- onSearchClick() {
|
|
|
- this.conditions(1, false); // 主动查询,第一页,非分页触发
|
|
|
- },
|
|
|
- handlePageChange(page) {
|
|
|
- this.conditions(page, true); // true 表示分页触发
|
|
|
- },
|
|
|
-
|
|
|
- conditions(page, isPageChange = false) {
|
|
|
- const tab = this.activeTab;
|
|
|
- this.$nextTick(() => {
|
|
|
- const comp = this.$refs.activeComponent;
|
|
|
- if (comp && typeof comp.reset === "function") {
|
|
|
- comp.reset();
|
|
|
- }
|
|
|
- });
|
|
|
-
|
|
|
- // 把后面接口请求部分放进延迟里,确保 reset 先执行完成
|
|
|
- setTimeout(() => {
|
|
|
- const condition = this.tabConditions[tab];
|
|
|
-
|
|
|
- if (tab === "Temperature") {
|
|
|
- const temperature = {
|
|
|
- windCode: condition.companyCode,
|
|
|
- windTurbineNumberList: [condition.unitvalue],
|
|
|
- startTime: this.$formatDateTWO(condition.timevalue[0]),
|
|
|
- endTime: this.$formatDateTWO(condition.timevalue[1]),
|
|
|
- pageNo: page,
|
|
|
- pageSize: 500,
|
|
|
- };
|
|
|
-
|
|
|
- const loading = this.$loading({
|
|
|
- lock: true,
|
|
|
- text: "温度诊断数据加载中,请稍候…",
|
|
|
- spinner: "el-icon-loading",
|
|
|
- background: "rgba(0, 0, 0, 0.8)",
|
|
|
- });
|
|
|
-
|
|
|
- const emptyEchartsData = {
|
|
|
- gearbox_oil: { timestamps: [], values: [] },
|
|
|
- generator_drive_end: { timestamps: [], values: [] },
|
|
|
- generator_nondrive_end: { timestamps: [], values: [] },
|
|
|
- main_bearing: { timestamps: [], values: [] },
|
|
|
- };
|
|
|
-
|
|
|
- const trendRequest = () => {
|
|
|
- const trendStart = performance.now();
|
|
|
- return axios
|
|
|
- .post("/AnalysisMulti/SPRT/trend", temperature)
|
|
|
- .then((res) => {
|
|
|
- const trendEnd = performance.now();
|
|
|
- console.log(
|
|
|
- `温度诊断 trend 接口耗时: ${(
|
|
|
- (trendEnd - trendStart) /
|
|
|
- 1000
|
|
|
- ).toFixed(2)}s`
|
|
|
- );
|
|
|
- const echartsdata = res.data.data || {};
|
|
|
- this.tabData[tab].echartsdata = echartsdata;
|
|
|
- })
|
|
|
- .catch((err) => {
|
|
|
- console.error("趋势图请求失败:", err);
|
|
|
- this.$message.error("温度趋势图数据请求失败,请稍后再试");
|
|
|
- });
|
|
|
- };
|
|
|
-
|
|
|
- const thresholdStart = performance.now();
|
|
|
- const thresholdReq = axios
|
|
|
- .post("/AnalysisMulti/temperature/threshold", temperature)
|
|
|
- .then((res) => {
|
|
|
- const thresholdEnd = performance.now();
|
|
|
- console.log(
|
|
|
- `温度诊断 threshold 接口耗时: ${(
|
|
|
- (thresholdEnd - thresholdStart) /
|
|
|
- 1000
|
|
|
- ).toFixed(2)}s`
|
|
|
- );
|
|
|
-
|
|
|
- const data = res.data.data.records || [];
|
|
|
- this.tabData[tab].codedata = data;
|
|
|
- this.tabData[tab].totalCount = res.data.data.totalSize || 0;
|
|
|
-
|
|
|
- if (!data.length) {
|
|
|
- this.$message.warning("暂无诊断数据");
|
|
|
- this.tabData[tab].echartsdata = emptyEchartsData;
|
|
|
- return Promise.resolve("skip trend");
|
|
|
- }
|
|
|
-
|
|
|
- return isPageChange ? Promise.resolve() : trendRequest();
|
|
|
- })
|
|
|
- .catch((err) => {
|
|
|
- console.error("温度诊断请求失败:", err);
|
|
|
- this.$message.error("温度诊断数据请求失败,请稍后再试");
|
|
|
- });
|
|
|
-
|
|
|
- Promise.resolve(thresholdReq).finally(() => {
|
|
|
- loading.close();
|
|
|
- });
|
|
|
- } else {
|
|
|
- const params = {
|
|
|
- samplingFrequency: condition.frequencyvalue,
|
|
|
- windCode: condition.companyCode,
|
|
|
- windTurbineNumberList: [condition.unitvalue],
|
|
|
- mesureNameList: [condition.monitoringvalue],
|
|
|
- startTime: this.$formatDateTWO(condition.timevalue[0]),
|
|
|
- endTime: this.$formatDateTWO(condition.timevalue[1]),
|
|
|
- pageNo: page,
|
|
|
- pageSize: 10,
|
|
|
- };
|
|
|
-
|
|
|
- const startTime = performance.now();
|
|
|
- axios
|
|
|
- .post("/ETLapi/waveData/getMesureDataWithSF", params)
|
|
|
- .then((res) => {
|
|
|
- const endTime = performance.now();
|
|
|
- console.log(
|
|
|
- `其他 tab 接口请求耗时: ${(endTime - startTime).toFixed(2)}ms`
|
|
|
- );
|
|
|
-
|
|
|
- const data = res.data || {};
|
|
|
- this.tabData[tab].codedata = data.datas || [];
|
|
|
- this.tabData[tab].totalCount = data.totalCount || 0;
|
|
|
- this.tabData[tab].totalPage = data.totalPage || 0;
|
|
|
- });
|
|
|
- }
|
|
|
- }, 300); // 延迟100毫秒执行接口请求逻辑
|
|
|
- },
|
|
|
- },
|
|
|
-};
|
|
|
-</script>
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- <style lang="scss" scoped>
|
|
|
-.global-variable {
|
|
|
- padding: 10px;
|
|
|
-}
|
|
|
-.head {
|
|
|
- padding: 5px 0;
|
|
|
- display: flex;
|
|
|
- justify-content: space-between;
|
|
|
-
|
|
|
- ul {
|
|
|
- display: flex;
|
|
|
- width: 500px;
|
|
|
- height: 65px;
|
|
|
- justify-content: space-between;
|
|
|
- li {
|
|
|
- cursor: pointer;
|
|
|
- padding: 8px 12px 0 12px;
|
|
|
- border-radius: 4px;
|
|
|
- transition: all 0.3s;
|
|
|
-
|
|
|
- &:hover {
|
|
|
- background-color: #f0f0f0;
|
|
|
- }
|
|
|
-
|
|
|
- &.active {
|
|
|
- background-color: #e6f7ff;
|
|
|
- border-bottom: 2px solid var(--header-bg);
|
|
|
-
|
|
|
- span {
|
|
|
- color: var(--header-bg);
|
|
|
- font-weight: bold;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- .Simg {
|
|
|
- width: 30px;
|
|
|
- height: 30px;
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- justify-content: center;
|
|
|
- margin: 0 auto;
|
|
|
-
|
|
|
- img {
|
|
|
- max-width: 100%;
|
|
|
- max-height: 100%;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- span {
|
|
|
- display: block;
|
|
|
- font-size: 12px;
|
|
|
- font-weight: 600;
|
|
|
- text-align: center;
|
|
|
- margin-top: 5px;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-.searchbox {
|
|
|
- display: flex;
|
|
|
- margin-bottom: 10px;
|
|
|
- align-items: center;
|
|
|
- flex-wrap: wrap;
|
|
|
- // padding-top: 10px;
|
|
|
- p {
|
|
|
- margin-right: 10px;
|
|
|
- margin-bottom: 0;
|
|
|
- margin-top: 10px;
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
-
|
|
|
- .el-select,
|
|
|
- .el-date-picker {
|
|
|
- margin-left: 10px;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- .el-select {
|
|
|
- width: 180px;
|
|
|
- }
|
|
|
- .search-btn {
|
|
|
- margin-top: 10px;
|
|
|
- }
|
|
|
-}
|
|
|
-.main-body {
|
|
|
- margin-top: 10px;
|
|
|
- // border: 1px solid #ebeef5;
|
|
|
- border-radius: 4px;
|
|
|
- padding: 10px;
|
|
|
- background: #fff;
|
|
|
-}
|
|
|
-
|
|
|
-.el-range-editor.el-input__inner {
|
|
|
- width: 370px;
|
|
|
-}
|
|
|
-
|
|
|
-/* 放在你的组件 <style scoped> 或全局样式里 */
|
|
|
-.custom-loading-style .el-loading-spinner i {
|
|
|
- font-size: 26px;
|
|
|
- color: #409eff; /* Element UI 主色调,更柔和 */
|
|
|
-}
|
|
|
-
|
|
|
-.custom-loading-style .el-loading-text {
|
|
|
- font-size: 14px;
|
|
|
- color: #303133;
|
|
|
- letter-spacing: 0.5px;
|
|
|
-}
|
|
|
-</style>
|