|
@@ -1,16 +1,503 @@
|
|
|
<template>
|
|
|
- <div>松动诊断</div>
|
|
|
+ <div>
|
|
|
+ <div class="TopBox">
|
|
|
+ <div class="rightdiv">
|
|
|
+ <el-table
|
|
|
+ ref="multipleTable"
|
|
|
+ :data="tableData"
|
|
|
+ tooltip-effect="dark"
|
|
|
+ style="width: 100%"
|
|
|
+ height="250"
|
|
|
+ >
|
|
|
+ <!-- <el-table-column fixed type="selection" width="55"> </el-table-column> -->
|
|
|
+ <el-table-column
|
|
|
+ prop="timeStamp"
|
|
|
+ label="时间"
|
|
|
+ align="center"
|
|
|
+ width="150"
|
|
|
+ >
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column
|
|
|
+ prop="samplingFrequency"
|
|
|
+ label="采样频率(Hz)"
|
|
|
+ align="center"
|
|
|
+ >
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column
|
|
|
+ prop="rotationalSpeed"
|
|
|
+ label="转速(rpm)"
|
|
|
+ align="center"
|
|
|
+ >
|
|
|
+ </el-table-column>
|
|
|
+ </el-table>
|
|
|
+ <div class="fenye">
|
|
|
+ <p><span>故障状态代码说明:</span>0代表正常,1代表报警,2代表危险</p>
|
|
|
+
|
|
|
+ <el-pagination
|
|
|
+ small
|
|
|
+ @current-change="handleCurrentChange"
|
|
|
+ :current-page="currentPage"
|
|
|
+ layout="total, prev, pager, next, jumper"
|
|
|
+ :total="totalCount"
|
|
|
+ :page-size="20"
|
|
|
+ ></el-pagination>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="leftdiv">
|
|
|
+ <div class="stateBox">
|
|
|
+ <h4>松动状态</h4>
|
|
|
+ <div class="state">
|
|
|
+ <p :style="{ backgroundColor: bearingStateColors.innerRing }">
|
|
|
+ 松动
|
|
|
+ </p>
|
|
|
+ </div>
|
|
|
+ <el-button
|
|
|
+ type="primary"
|
|
|
+ size="small"
|
|
|
+ @click="automaticDiagnosis"
|
|
|
+ class="btn-auto"
|
|
|
+ >自动诊断</el-button
|
|
|
+ >
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="Btn">
|
|
|
+ <div style="height: 200px">
|
|
|
+ <bing :result="result"> </bing>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="minp">
|
|
|
+ <p class="PText">
|
|
|
+ <span><i class="color1"></i>正常</span
|
|
|
+ ><span><i class="color2"></i>报警</span
|
|
|
+ ><span><i class="color3"></i>危险</span>
|
|
|
+ </p>
|
|
|
+
|
|
|
+ <h4>诊断步骤:</h4>
|
|
|
+ <p>1、选择振动测点与起止时间,点击“查询;</p>
|
|
|
+ <p>2、对松动“参数设置”输入相关信息;</p>
|
|
|
+ <p>3、点击“自动诊断”输出最终轴承状态结果。</p>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="bottomBox">
|
|
|
+ <div class="BtLeft">
|
|
|
+ <h4>测点基础信息</h4>
|
|
|
+ <el-empty
|
|
|
+ :image="kfImg"
|
|
|
+ description="功能开发中"
|
|
|
+ style="padding: 48px 0"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="BtLeft">
|
|
|
+ <h4>松动故障状态趋势图</h4>
|
|
|
+ <el-empty
|
|
|
+ v-if="this.xData.length === 0 || this.yData.length === 0"
|
|
|
+ description="暂无数据"
|
|
|
+ style="padding: 48px 0"
|
|
|
+ ></el-empty>
|
|
|
+ <Eecharts
|
|
|
+ v-else
|
|
|
+ style="height: 300px"
|
|
|
+ :xData="xData"
|
|
|
+ :yData="yData"
|
|
|
+ :yNames="['松动故障']"
|
|
|
+ yAxisName="松动故障状态"
|
|
|
+ ></Eecharts>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <el-dialog title="参数" :visible.sync="dialogVisible" width="50%">
|
|
|
+ <div class="BtRight">
|
|
|
+ <h4>参数设置</h4>
|
|
|
+ <div class="BtRightDiv">
|
|
|
+ <p class="BtRightP">
|
|
|
+ <span>发电机到松动测点的转速传动比</span>
|
|
|
+
|
|
|
+ <span
|
|
|
+ ><el-input
|
|
|
+ v-model="transmissionRatio"
|
|
|
+ size="small"
|
|
|
+ v-number-only
|
|
|
+ ></el-input
|
|
|
+ ></span>
|
|
|
+ </p>
|
|
|
+
|
|
|
+ <h4>报警阈值输入</h4>
|
|
|
+ <div class="canshu">
|
|
|
+ <p class="BtRightP">
|
|
|
+ <span class="label-text">振动速度报警阈值(mm/s)</span>
|
|
|
+ <span
|
|
|
+ ><el-input
|
|
|
+ v-model="vibrationSpeedAlarmThreshold"
|
|
|
+ size="small"
|
|
|
+ v-number-only
|
|
|
+ ></el-input
|
|
|
+ ></span>
|
|
|
+ </p>
|
|
|
+
|
|
|
+ <p class="BtRightP">
|
|
|
+ <span class="label-text">振动速度危险阈值(mm/s)</span>
|
|
|
+ <span
|
|
|
+ ><el-input
|
|
|
+ v-model="vibrationSpeedDangerThreshold"
|
|
|
+ size="small"
|
|
|
+ v-number-only
|
|
|
+ ></el-input
|
|
|
+ ></span>
|
|
|
+ </p>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="dialog-footer">
|
|
|
+ <el-button type="primary" size="small" @click="submit"
|
|
|
+ >确定</el-button
|
|
|
+ >
|
|
|
+ </div>
|
|
|
+ </el-dialog>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
</template>
|
|
|
|
|
|
<script>
|
|
|
+import kfImg from "@/assets/KF.png";
|
|
|
+import Eecharts from "./Eecharts.vue";
|
|
|
+import bing from "./bing.vue";
|
|
|
+import { cacheEntryPossiblyAdded } from "plotly.js-dist";
|
|
|
export default {
|
|
|
+ components: { Eecharts, bing },
|
|
|
+ props: {
|
|
|
+ codedata: {
|
|
|
+ type: Array,
|
|
|
+ default: () => [],
|
|
|
+ },
|
|
|
+ totalCount: {
|
|
|
+ type: Number,
|
|
|
+ default: 0,
|
|
|
+ },
|
|
|
+ totalPage: {
|
|
|
+ type: Number,
|
|
|
+ default: 0,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ kfImg: kfImg,
|
|
|
+ tableData: [],
|
|
|
+ // 添加新的数据属性用于绑定输入框的值
|
|
|
+ transmissionRatio: "",
|
|
|
+ bearingPitchDiameter: "",
|
|
|
+ rollingElementDiameter: "",
|
|
|
+ rollingElementCount: "",
|
|
|
+ contactAngle: "",
|
|
|
+ vibrationSpeedAlarmThreshold: "",
|
|
|
+ vibrationSpeedDangerThreshold: "",
|
|
|
+ envelopeTotalAlarmThreshold: "",
|
|
|
+ envelopeTotalDangerThreshold: "",
|
|
|
+ // 分页
|
|
|
|
|
|
-}
|
|
|
+ currentPage: 1,
|
|
|
+ total: 1,
|
|
|
+
|
|
|
+ xData: [],
|
|
|
+ yData: [],
|
|
|
+ // 颜色判断
|
|
|
+ bearingStateColors: {
|
|
|
+ innerRing: "#80808057",
|
|
|
+ outerRing: "#80808057",
|
|
|
+ rollingElement: "#80808057",
|
|
|
+ cage: "#80808057",
|
|
|
+ },
|
|
|
+ hasError: false, // 标志是否已经显示过错误提示
|
|
|
+ result: {},
|
|
|
+ dialogVisible: false,
|
|
|
+ };
|
|
|
+ },
|
|
|
+ created() {},
|
|
|
+ watch: {
|
|
|
+ codedata: {
|
|
|
+ handler(newVal) {
|
|
|
+ this.tableData = newVal;
|
|
|
+ },
|
|
|
+ immediate: true, // 组件创建时立刻执行一次
|
|
|
+ deep: true, // 如果 codedata 是复杂对象,建议加上
|
|
|
+ },
|
|
|
+ },
|
|
|
+
|
|
|
+ methods: {
|
|
|
+ toggleSelection(rows) {
|
|
|
+ if (rows) {
|
|
|
+ rows.forEach((row) => {
|
|
|
+ this.$refs.multipleTable.toggleRowSelection(row);
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ this.$refs.multipleTable.clearSelection();
|
|
|
+ }
|
|
|
+ },
|
|
|
+ handleSelectionChange(val) {
|
|
|
+ this.multipleSelection = val;
|
|
|
+ },
|
|
|
+ handleCurrentChange(val) {
|
|
|
+ console.log(`当前页: ${val}`);
|
|
|
+
|
|
|
+ this.currentPage = val; // 子组件内部更新当前页
|
|
|
+ this.$emit("updatePage", this.currentPage); // 通知父组件,把当前页传出去
|
|
|
+ },
|
|
|
+ automaticDiagnosis() {
|
|
|
+ this.dialogVisible = true;
|
|
|
+ },
|
|
|
+ submit() {
|
|
|
+ // 验证必填项
|
|
|
+ const requiredFields = [
|
|
|
+ { field: this.transmissionRatio, name: "发动机到轴承测点转速传动比" },
|
|
|
+ { field: this.bearingPitchDiameter, name: "轴承节圆直径D(mm)" },
|
|
|
+ { field: this.rollingElementDiameter, name: "滚动体直径d(mm)" },
|
|
|
+ { field: this.rollingElementCount, name: "滚动体个数Z(个)" },
|
|
|
+ { field: this.contactAngle, name: "接触角α(°)" },
|
|
|
+ {
|
|
|
+ field: this.vibrationSpeedAlarmThreshold,
|
|
|
+ name: "振动速度报警阈值(mm/s)",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ field: this.vibrationSpeedDangerThreshold,
|
|
|
+ name: "振动速度危险阈值(mm/s)",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ field: this.envelopeTotalAlarmThreshold,
|
|
|
+ name: "包络总值报警阈值(gE)",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ field: this.envelopeTotalDangerThreshold,
|
|
|
+ name: "包络总值危险阈值(gE)",
|
|
|
+ },
|
|
|
+ ];
|
|
|
+
|
|
|
+ // 记录是否已弹出过错误提示
|
|
|
+ let hasError = false;
|
|
|
+
|
|
|
+ // 只检查必填项的字段是否为空
|
|
|
+ // for (const { field, name } of requiredFields) {
|
|
|
+ // if (!field && !hasError) {
|
|
|
+ // // 弹出提示并标记已经出现错误提示
|
|
|
+ // this.$message.error(`${name} 是必填项`);
|
|
|
+ // hasError = true; // 标记已经弹出过错误提示
|
|
|
+ // return; // 停止执行后续逻辑
|
|
|
+ // }
|
|
|
+ // }
|
|
|
+
|
|
|
+ // 如果验证通过,继续执行后续逻辑
|
|
|
+ const newProps = this.tableData.map(() => ({
|
|
|
+ innerRingFault: Math.floor(Math.random() * 3).toString(),
|
|
|
+ // outerRingFault: Math.floor(Math.random() * 3).toString(),
|
|
|
+ // rollingElementFault: Math.floor(Math.random() * 3).toString(),
|
|
|
+ // cageFault: Math.floor(Math.random() * 3).toString(),
|
|
|
+ }));
|
|
|
+
|
|
|
+ this.tableData.forEach((row, index) => {
|
|
|
+ this.$set(this.tableData, index, {
|
|
|
+ ...row,
|
|
|
+ ...newProps[index], // 用每一行自己生成的随机数
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ const faultValues = [
|
|
|
+ ...this.tableData.map((record) => record.innerRingFault),
|
|
|
+ // ...this.tableData.map((record) => record.outerRingFault),
|
|
|
+ // ...this.tableData.map((record) => record.rollingElementFault),
|
|
|
+ // ...this.tableData.map((record) => record.cageFault),
|
|
|
+ ];
|
|
|
+
|
|
|
+ // 统计各个值出现的次数
|
|
|
+ const counter = faultValues.reduce((acc, value) => {
|
|
|
+ acc[value] = (acc[value] || 0) + 1;
|
|
|
+ return acc;
|
|
|
+ }, {});
|
|
|
+
|
|
|
+ // 构造统计结果对象
|
|
|
+ this.result = {
|
|
|
+ 1: counter["0"] || 0,
|
|
|
+ 2: counter["1"] || 0,
|
|
|
+ 3: counter["2"] || 0,
|
|
|
+ };
|
|
|
+
|
|
|
+ // 更新颜色状态
|
|
|
+ const fields = [
|
|
|
+ { key: "innerRingFault", colorKey: "innerRing" },
|
|
|
+ // { key: "outerRingFault", colorKey: "outerRing" },
|
|
|
+ // { key: "rollingElementFault", colorKey: "rollingElement" },
|
|
|
+ // { key: "cageFault", colorKey: "cage" },
|
|
|
+ ];
|
|
|
+
|
|
|
+ fields.forEach(({ key, colorKey }) => {
|
|
|
+ const values = newProps.map((item) => Number(item[key]));
|
|
|
+ const maxVal = Math.max(...values);
|
|
|
+ let color = "#80808057"; // 默认灰色
|
|
|
+ if (maxVal === 0) color = "#8AE359"; // 无故障
|
|
|
+ else if (maxVal === 1) color = "#EECB5F"; // 警告
|
|
|
+ else if (maxVal === 2) color = "#F7715F"; // 危险
|
|
|
+
|
|
|
+ this.bearingStateColors[colorKey] = color; // 更新颜色
|
|
|
+ });
|
|
|
+
|
|
|
+ // 更新趋势图数据
|
|
|
+ // 更新趋势图数据(用tableData,不是newProps)
|
|
|
+ this.xData = this.tableData.map((item) => item.timeStamp);
|
|
|
+ this.yData = fields.map(({ key }) =>
|
|
|
+ this.tableData.map((item) => Number(item[key]))
|
|
|
+ );
|
|
|
+ this.dialogVisible = false;
|
|
|
+ },
|
|
|
+ },
|
|
|
+};
|
|
|
</script>
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
-div{
|
|
|
- height: 300px;
|
|
|
- background: #7e0505;;
|
|
|
+h4 {
|
|
|
+ margin-bottom: 5px;
|
|
|
+ font-weight: 600;
|
|
|
+}
|
|
|
+.TopBox {
|
|
|
+ height: 280px;
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-around;
|
|
|
+ .leftdiv {
|
|
|
+ width: 50%;
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-around;
|
|
|
+ .stateBox {
|
|
|
+ .state {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ justify-content: center; /* 整体居中 */
|
|
|
+ align-items: center;
|
|
|
+ height: 200px;
|
|
|
+ gap: 20px; /* 控制间距 */
|
|
|
+ p {
|
|
|
+ width: 150px;
|
|
|
+ height: 40px;
|
|
|
+ background: rgb(227, 227, 227);
|
|
|
+ color: rgb(50, 50, 50);
|
|
|
+ text-align: center;
|
|
|
+ align-content: center;
|
|
|
+ font-weight: 600;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .btn-auto {
|
|
|
+ margin-top: 10px;
|
|
|
+ width: 100%;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .Btn {
|
|
|
+ width: 50%;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column; /* 垂直排列 */
|
|
|
+ justify-content: space-between; /* 顶部和底部对齐 */
|
|
|
+ min-height: 100px; /* 确保容器有足够高度 */
|
|
|
+ margin: 10px 0;
|
|
|
+ .PText {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-around;
|
|
|
+
|
|
|
+ span {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ i {
|
|
|
+ width: 30px;
|
|
|
+ height: 15px;
|
|
|
+ margin-right: 5px;
|
|
|
+ }
|
|
|
+ .color1 {
|
|
|
+ background-color: #8ae359;
|
|
|
+ }
|
|
|
+ .color2 {
|
|
|
+ background-color: #eecb5f;
|
|
|
+ }
|
|
|
+ .color3 {
|
|
|
+ background-color: #f7715f;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ margin: 10px 0;
|
|
|
+ .minp {
|
|
|
+ font-size: 12px;
|
|
|
+ margin-top: auto; /* 自动推到最底部 */
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .rightdiv {
|
|
|
+ width: 50%;
|
|
|
+ .fenye {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ margin: 5px 0;
|
|
|
+ font-size: 11px;
|
|
|
+ line-height: 30px;
|
|
|
+ span {
|
|
|
+ font-weight: 600;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.bottomBox {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ margin-top: 10px;
|
|
|
+ .BtLeft {
|
|
|
+ border: 1px solid rgb(231, 231, 231);
|
|
|
+ width: 49.5%;
|
|
|
+ padding: 10px;
|
|
|
+
|
|
|
+ }
|
|
|
+ .BtRight {
|
|
|
+ // width: 49%;
|
|
|
+ border: 1px solid rgb(231, 231, 231);
|
|
|
+ padding: 10px;
|
|
|
+ .BtRightDiv {
|
|
|
+ padding: 0 10px;
|
|
|
+ h4 {
|
|
|
+ font-size: 14px;
|
|
|
+ }
|
|
|
+ .BtRightP {
|
|
|
+ line-height: 30px;
|
|
|
+ font-size: 12px;
|
|
|
+ display: flex;
|
|
|
+ margin-bottom: 5px;
|
|
|
+ width: 50%;
|
|
|
+ span {
|
|
|
+ margin-left: 10px;
|
|
|
+ .el-input {
|
|
|
+ width: 100px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .label-text {
|
|
|
+ width: 140px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .canshu {
|
|
|
+ display: flex;
|
|
|
+ flex-wrap: wrap;
|
|
|
+ justify-content: space-between;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .dialog-footer {
|
|
|
+ margin-top: 20px;
|
|
|
+ text-align: right;
|
|
|
+ }
|
|
|
+}
|
|
|
+::v-deep .el-table__cell {
|
|
|
+ padding: 2px 0;
|
|
|
+ font-size: 12px;
|
|
|
}
|
|
|
+.el-empty {
|
|
|
+ display: flex;
|
|
|
+ justify-content: center;
|
|
|
+ align-items: center;
|
|
|
+ flex-direction: column;
|
|
|
+ text-align: center;
|
|
|
+ box-sizing: border-box;
|
|
|
+ // padding: 40px 0;
|
|
|
+ height: 310px;}
|
|
|
</style>
|