vibration.vue 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042
  1. <template>
  2. <div class="global-variable">
  3. <div class="head">
  4. <div class="headleft">
  5. <div @click="generate('1')" class="picture">
  6. <img src="@/assets/analyse/03.png" alt="" />
  7. <p>时域图</p>
  8. </div>
  9. <div @click="generate('2')" class="picture">
  10. <img src="@/assets/analyse/04.png" alt="" />
  11. <p>频谱图</p>
  12. </div>
  13. <div @click="generate('3')" class="picture">
  14. <img src="@/assets/analyse/01.png" alt="" />
  15. <p>包络谱图</p>
  16. </div>
  17. <div @click="tendency" class="picture">
  18. <img src="@/assets/analyse/02.png" alt="" />
  19. <p>趋势图</p>
  20. </div>
  21. </div>
  22. <div class="headright">
  23. <img src="@/assets/analyse/07.png" alt="全部缩小" @click="suoxiao" />
  24. <img src="@/assets/analyse/05.png" alt="全部展开" @click="zhankai" />
  25. <img src="@/assets/analyse/06.png" alt="全部关闭" @click="guanbi" />
  26. </div>
  27. </div>
  28. <div class="searchbox">
  29. <p>
  30. 单位:
  31. <selecttree
  32. size="small"
  33. style="width: 180px"
  34. placeholder="请选择所属公司"
  35. :list="parentOpt"
  36. type="1"
  37. v-model="companyCode"
  38. @change="parentChange"
  39. :defaultParentProps="{
  40. children: 'children',
  41. label: 'companyName',
  42. value: 'codeNumber',
  43. }"
  44. >
  45. </selecttree>
  46. </p>
  47. <p>
  48. 风机:
  49. <el-select
  50. style="width: 150px"
  51. v-model="unitvalue"
  52. @change="getchedian"
  53. placeholder="请选择"
  54. size="small"
  55. >
  56. <el-option
  57. v-for="item in unitoptions"
  58. :key="item.engineCode"
  59. :label="item.engineName"
  60. :value="item.engineCode"
  61. >
  62. </el-option>
  63. </el-select>
  64. </p>
  65. <p>
  66. 测点:
  67. <el-select
  68. v-model="monitoringvalue"
  69. clearable
  70. size="small"
  71. placeholder="请选择"
  72. >
  73. <el-option
  74. v-for="item in monitoringoptions"
  75. :key="item.itemKey"
  76. :label="item.itemValue"
  77. :value="item.itemKey"
  78. >
  79. </el-option>
  80. </el-select>
  81. </p>
  82. <p>
  83. 时间:
  84. <el-date-picker
  85. v-model="timevalue"
  86. type="datetimerange"
  87. value-format="yyyy-MM-dd HH:mm:ss"
  88. range-separator="至"
  89. start-placeholder="开始日期"
  90. end-placeholder="结束日期"
  91. size="small"
  92. >
  93. </el-date-picker>
  94. </p>
  95. <el-button type="primary" size="small" @click="conditions"
  96. >查询</el-button
  97. >
  98. <el-button size="small" @click="outputFile">导出</el-button>
  99. </div>
  100. <div class="main-body">
  101. <div class="data-map">
  102. <div
  103. class="chart-area"
  104. v-for="(item, index) in fourList"
  105. :key="item.index"
  106. @mouseover="setCurrent(item.rowData)"
  107. @mouseleave="setCurrent(oldCurrentRow)"
  108. >
  109. <div class="dialog-actions">
  110. <p>{{ item.name }}</p>
  111. <span>
  112. <i
  113. class="el-icon-minus"
  114. @click="lessen(index)"
  115. style="cursor: pointer; margin-right: 10px"
  116. ></i>
  117. <i
  118. class="el-icon-full-screen"
  119. @click="amplifier(index)"
  120. style="cursor: pointer; margin-right: 10px"
  121. ></i>
  122. <i
  123. class="el-icon-close"
  124. @click="close(index)"
  125. style="cursor: pointer"
  126. ></i>
  127. </span>
  128. </div>
  129. <div
  130. class="subject"
  131. :class="{
  132. minimized: item.isMinimized,
  133. }"
  134. v-loading="item.loading"
  135. >
  136. <!-- {{ item.rowData }} -->
  137. <p v-if="item.name != '趋势图'">
  138. 测点路径:{{
  139. NewgetDetectionPointCn(item?.rowData?.mesurePointName)
  140. }}-{{ item?.rowData?.windTurbineNumber }}
  141. <span>采样频率: {{ item?.rowData?.samplingFrequency }}(Hz)</span>
  142. <span
  143. >发电机转速: {{ item?.rowData?.rotationalSpeed }}(rpm)
  144. </span>
  145. <span>采样时间: {{ item?.rowData?.timeStamp }} </span>
  146. <!-- <span>有效值: {{XrmsValue}} (m/s2)</span> -->
  147. </p>
  148. <!-- {{ samplingTime }} -->
  149. <div v-if="item.name === '时域图'">
  150. <timedomaincharts
  151. :timeListTwo="item.timeListTwo"
  152. :currentIndex="currentIndex"
  153. :activeIndex="index"
  154. :tableDataList="tableDataList"
  155. :ids="[currentRow.id]"
  156. :currentRow="currentRow"
  157. :windCode="windCode"
  158. @update:currentIndex="handleCurrentIndexUpdate"
  159. @update-previous-row="goToPreviousRow"
  160. @update-next-row="goToNextRow"
  161. @handleLoading="handleLoading"
  162. ></timedomaincharts>
  163. </div>
  164. <div v-if="item.name === '频谱图'">
  165. <spectrogramcharts
  166. @updateXrms="handleXrmsUpdate"
  167. :spectrumListTwo="item.spectrumListTwo"
  168. :currentIndex="currentIndex"
  169. :tableDataList="tableDataList"
  170. :activeIndex="index"
  171. :ids="[currentRow.id]"
  172. :currentRow="currentRow"
  173. :windCode="windCode"
  174. @update:currentIndex="handleCurrentIndexUpdate"
  175. @update-previous-row="goToPreviousRow"
  176. @update-next-row="goToNextRow"
  177. @handleLoading="handleLoading"
  178. ></spectrogramcharts>
  179. </div>
  180. <div v-if="item.name === '包络谱图'">
  181. <envelopecharts
  182. @updateXrms="handleXrmsUpdate"
  183. :envelopeListTwo="item.envelopeListTwo"
  184. :currentIndex="currentIndex"
  185. :tableDataList="tableDataList"
  186. :activeIndex="index"
  187. :currentRow="currentRow"
  188. :ids="[currentRow.id]"
  189. :windCode="windCode"
  190. @update:currentIndex="handleCurrentIndexUpdate"
  191. @update-previous-row="goToPreviousRow"
  192. @update-next-row="goToNextRow"
  193. @update:modelValue="handleModelUpdate"
  194. @handleLoading="handleLoading"
  195. ></envelopecharts>
  196. </div>
  197. <div v-if="item.name === '趋势图'">
  198. <tendencycharts
  199. :qsList="qsList"
  200. :activeIndex="index"
  201. ></tendencycharts>
  202. </div>
  203. </div>
  204. </div>
  205. </div>
  206. <div class="data-origin">
  207. <el-table
  208. height="600"
  209. ref="singleTable"
  210. :data="tableDataList"
  211. :current-row-key="currentIndex"
  212. @current-change="handleCurrentChange"
  213. highlight-current-row
  214. style="width: 100%"
  215. :row-class-name="tableRowClassName"
  216. id="Table1"
  217. >
  218. <el-table-column type="index" label="排序" fixed> </el-table-column>
  219. <el-table-column prop="timeStamp" label="采样时间" width="180px">
  220. </el-table-column>
  221. <el-table-column label="测点名称" width="200px">
  222. <template slot-scope="scope">
  223. {{
  224. pointNameMap[scope.row.mesurePointName] ||
  225. scope.row.mesurePointName
  226. }}
  227. </template>
  228. </el-table-column>
  229. <!-- <el-table-column prop="companyName" label="场站">
  230. {{ getCompanyLabel(scope.row.companyCode) }}
  231. </el-table-column> -->
  232. <el-table-column prop="windTurbineNumber" label="风机" width="120px">
  233. </el-table-column>
  234. <el-table-column
  235. prop="samplingFrequency"
  236. label="采样频率(Hz)"
  237. align="center"
  238. width="120px"
  239. >
  240. </el-table-column>
  241. <el-table-column
  242. prop="rotationalSpeed"
  243. label="发电机转速(rpm)"
  244. align="center"
  245. width="150px"
  246. >
  247. </el-table-column>
  248. </el-table>
  249. <div class="pagination-wrapper">
  250. <el-pagination
  251. :current-page="currentPage"
  252. :page-size="pageSize"
  253. :total="allTableDataList.length"
  254. layout="prev, pager, next"
  255. @current-change="handlePageChange"
  256. >
  257. </el-pagination>
  258. </div>
  259. </div>
  260. </div>
  261. </div>
  262. </template>
  263. <script>
  264. import * as FileSaver from "file-saver";
  265. import * as XLSX from "xlsx";
  266. import {
  267. getSysOrganizationAuthTreeByRoleId,
  268. windEngineGrouPage,
  269. queryDetectionDic,
  270. } from "@/api/ledger.js";
  271. import selecttree from "../../components/selecttree.vue";
  272. import envelopecharts from "./components/envelopecharts.vue";
  273. import spectrogramcharts from "./components/spectrogramcharts.vue";
  274. import tendencycharts from "./components/tendencycharts.vue";
  275. import timedomaincharts from "./components/timedomaincharts.vue";
  276. import axios from "axios";
  277. // 放在 <script> 外部
  278. export default {
  279. components: {
  280. envelopecharts,
  281. spectrogramcharts,
  282. tendencycharts,
  283. timedomaincharts,
  284. selecttree,
  285. },
  286. data() {
  287. return {
  288. chartData: [],
  289. chartLabels: [],
  290. unitvale: "",
  291. company: "",
  292. companyoptions: [],
  293. unitvalue: "",
  294. unitoptions: [],
  295. monitoringvalue: "",
  296. monitoringoptions: [
  297. // {
  298. // detectionPointEn: "name",
  299. // detectionPointCn: "中文",
  300. // },
  301. ],
  302. fourList: [],
  303. currentRow: null, // 用于存储当前选中的行
  304. currentIndex: 0,
  305. isChartVisible: false,
  306. parentOpt: [],
  307. defaultdata: {},
  308. companyCode: "",
  309. windCode: "",
  310. maplist: {},
  311. timevalue: [], // 绑定 el-date-picker 的值
  312. startTime: "", // 开始时间
  313. endTime: "", // 结束时间
  314. allTableDataList: [], // 保存全部数据
  315. tableDataList: [], // 当前分页显示的数据
  316. currentPage: 1, // 当前页
  317. pageSize: 50,
  318. samplingTime: "", // 采样时间
  319. timeListTwo: {},
  320. spectrumList: {},
  321. envelopeList: {},
  322. qsList: {},
  323. CdNamw: "",
  324. chartsData: {},
  325. shuju: {},
  326. spectrumListTwo: {},
  327. envelopeListTwo: {},
  328. oldCurrentRow: {},
  329. XrmsValue: 0, // 默认值
  330. pointNameMap: {
  331. main_bearing_radial_vertical_vibration: "主轴承径向垂直振动",
  332. main_bearing_radial_vibration: "主轴承径向振动",
  333. main_bearing_radial_horizontal_vibration: "主轴承径向水平振动",
  334. main_bearing_axial_vibration: "主轴承轴向振动",
  335. front_main_bearing_radial_vertical_vibration: "前主轴承径向垂直振动",
  336. front_main_bearing_radial_vibration: "前主轴承径向振动",
  337. front_main_bearing_radial_horizontal_vibration: "前主轴承径向水平振动",
  338. front_main_bearing_axial_vibration: "前主轴承轴向振动",
  339. generator_radial_1_vibration: "发电机径向1振动",
  340. generator_radial_2_vibration: "发电机径向2振动",
  341. generator_speed: "发电机转速",
  342. generator_non_drive_end_radial_vibration: "发电机非驱动端径向振动",
  343. generator_drive_end_radial_vibration: "发电机驱动端径向振动",
  344. rear_main_bearing_radial_vertical_vibration: "后主轴承径向垂直振动",
  345. rear_main_bearing_radial_vibration: "后主轴承径向振动",
  346. rear_main_bearing_radial_horizontal_vibration: "后主轴承径向水平振动",
  347. rear_main_bearing_axial_vibration: "后主轴承轴向振动",
  348. stator_radial_horizontal_vibration: "定子径向水平振动",
  349. gearbox_first_stage_planet_large_ring_radial_vibration:
  350. "齿轮箱一级行星级大齿圈径向振动",
  351. gearbox_first_stage_planet_radial_vibration: "齿轮箱一级行星级径向振动",
  352. gearbox_third_stage_planet_radial_vibration: "齿轮箱三级行星级径向振动",
  353. gearbox_second_stage_planet_large_ring_radial_vibration:
  354. "齿轮箱二级行星级大齿圈径向振动",
  355. gearbox_second_stage_planet_radial_vibration:
  356. "齿轮箱二级行星级径向振动",
  357. gearbox_second_stage_planet_axial_vibration: "齿轮箱二级行星级轴向振动",
  358. gearbox_low_speed_shaft_output_end_radial_vibration:
  359. "齿轮箱低速轴输出端径向振动",
  360. gearbox_input_end_radial_vibration: "齿轮箱输入端径向振动",
  361. gearbox_output_shaft_axial_vibration: "齿轮箱输出轴轴向振动",
  362. gearbox_high_speed_shaft_output_end_radial_vibration:
  363. "齿轮箱高速轴输出端径向振动",
  364. gearbox_high_speed_shaft_output_end_axial_vibration:
  365. "齿轮箱高速轴输出端轴向振动",
  366. },
  367. // demo演示所需,必要时可删除
  368. unitvalue: "WOG01315",
  369. unitoptions: [
  370. {
  371. engineCode: "WOG01315",
  372. engineName: "#37",
  373. },
  374. ],
  375. monitoringvalue: "main_bearing_radial_horizontal_vibration",
  376. monitoringoptions: [
  377. {
  378. itemKey: "main_bearing_radial_horizontal_vibration",
  379. itemValue: "主轴承径向水平振动",
  380. },
  381. ],
  382. timevalue: ["2024-07-01 00:00:00", "2024-08-31 00:00:00"],
  383. maplist: {
  384. codeNumber: "WOF046400029",
  385. companyCode: "WOF046400029",
  386. },
  387. companyCode: "WOF046400029",
  388. windCode: "WOF046400029",
  389. };
  390. },
  391. created() {
  392. if (process.env.VUE_APP_Helath === "demo") {
  393. this.GETtreedemo();
  394. } else {
  395. this.GETtree();
  396. }
  397. },
  398. watch: {
  399. // 监听 timeList 的变化
  400. currentRow(newVal, oldVal) {
  401. if (newVal) {
  402. // console.log(newVal, oldVal);
  403. this.oldCurrentRow = oldVal;
  404. } else {
  405. console.error("currentRow is undefined or null");
  406. }
  407. },
  408. },
  409. methods: {
  410. handleXrmsUpdate(value) {
  411. this.XrmsValue = value; // 更新有效值
  412. },
  413. handleLoading(currentRow, loading, activeIndex, params) {
  414. if (loading) {
  415. this.$set(this.fourList[activeIndex], "loading", loading);
  416. return;
  417. }
  418. this.$set(this.fourList[activeIndex], "rowData", currentRow);
  419. this.$set(this.fourList[activeIndex], "loading", false);
  420. },
  421. onRowClick(row) {
  422. this.currentRow = row; // 选中行数据
  423. },
  424. getDetectionPointCn(detectionPointEn) {
  425. const point = this.monitoringoptions?.find(
  426. (option) => option.detectionPointEn === detectionPointEn
  427. );
  428. return point ? point?.detectionPointCn : null; // 如果没有找到对应项,返回 null
  429. },
  430. NewgetDetectionPointCn(key) {
  431. return this.pointNameMap[key] || key;
  432. },
  433. getCompanyLabel(companyCode) {
  434. const selectedOption = this.parentOpt?.find(
  435. (option) => option.codeNumber === companyCode
  436. );
  437. return selectedOption ? selectedOption.companyName : ""; // Return companyName or empty string if not found
  438. },
  439. // 获取风场
  440. async GETtree() {
  441. const res = await getSysOrganizationAuthTreeByRoleId();
  442. const treedata = res.data;
  443. const processedData = this.processTreeData(treedata);
  444. this.parentOpt = processedData;
  445. this.defaultdata = res.data[0];
  446. },
  447. async GETtreedemo() {
  448. const res = await getSysOrganizationAuthTreeByRoleId();
  449. const treedata = res.data;
  450. const processedData = this.processTreeData(treedata);
  451. this.parentOpt = processedData;
  452. this.defaultdata = res.data[0];
  453. // demo演示
  454. this.$nextTick(() => {
  455. this.companyCode = "WOF046400029";
  456. this.windCode = "WOF046400029";
  457. });
  458. },
  459. parentChange(data) {
  460. this.maplist = data;
  461. this.maplistArr = data;
  462. let paramsData = {
  463. fieldCode: this.maplist.codeNumber,
  464. pageNum: 1,
  465. pageSize: 99,
  466. };
  467. this.unitvalue = "";
  468. this.monitoringvalue = "";
  469. // 获取风机
  470. windEngineGrouPage(paramsData).then((res) => {
  471. this.unitoptions = res.data.list;
  472. this.windCode = this.companyCode;
  473. });
  474. if (data.codeType === "field") {
  475. if (this.parseCoordinates(data.longitudeAndLatitudeString).length > 0) {
  476. return;
  477. }
  478. } else {
  479. const dataMapList = data.children;
  480. dataMapList.forEach((element) => {
  481. if (
  482. this.parseCoordinates(element.longitudeAndLatitudeString).length >
  483. 0 &&
  484. element.codeType === "field"
  485. ) {
  486. return;
  487. }
  488. });
  489. }
  490. },
  491. processTreeData(treeData) {
  492. const processedData = [];
  493. function processNode(node) {
  494. if (node.codeType === "field") {
  495. node.companyName = node.fieldName;
  496. }
  497. if (node.children && node.children.length > 0) {
  498. node.children.forEach((child) => {
  499. processNode(child);
  500. });
  501. }
  502. }
  503. treeData.forEach((root) => {
  504. processNode(root);
  505. processedData.push(root);
  506. });
  507. return processedData;
  508. },
  509. parseCoordinates(input) {
  510. if (input && typeof input === "string") {
  511. return input.split(",").map(Number);
  512. }
  513. // debugger;
  514. return [];
  515. },
  516. // 获取测点
  517. getchedian(value) {
  518. axios
  519. .post(
  520. `/ETLapi/waveData/getAllMesurePointName/${this.companyCode}/${value}`
  521. )
  522. .then((res) => {
  523. this.monitoringvalue = "";
  524. if (res.data.code === 500) {
  525. this.monitoringoptions = []; // 清空旧数据
  526. this.$message({
  527. message: res.data.message || "未知错误",
  528. type: "warning",
  529. });
  530. return;
  531. }
  532. if (res.data.code === 200) {
  533. const datas = Array.isArray(res.data.datas) ? res.data.datas : [];
  534. this.monitoringoptions = datas;
  535. if (datas.length === 0) {
  536. this.$message({
  537. message: "暂无数据",
  538. type: "warning",
  539. });
  540. }
  541. }
  542. })
  543. .catch((err) => {
  544. console.error("请求失败", err);
  545. this.monitoringoptions = []; // 防止报错后保持旧数据
  546. });
  547. },
  548. handleModelUpdate(data) {
  549. // 将子组件的值作为查询参数传递给查询接口
  550. this.xiaoval = data.xiaoval;
  551. this.daval = data.daval;
  552. },
  553. // 上一条数据
  554. goToPreviousRow(type, activeIndex) {
  555. if (this.tableDataList.length === 0) return;
  556. // 更新当前索引,向前循环
  557. this.currentIndex =
  558. this.currentIndex === 0
  559. ? this.tableDataList.length - 1
  560. : this.currentIndex - 1;
  561. const currentRow = this.tableDataList[this.currentIndex];
  562. this.setCurrent(currentRow);
  563. const params = {
  564. ids: currentRow.id,
  565. windCode: this.companyCode,
  566. // windCode: "SKF001",
  567. };
  568. // 根据type加载不同的数据
  569. if (type === 1) {
  570. // Type 1: 加载时域数据
  571. this.$set(this.fourList[activeIndex], "loading", true);
  572. params.analysisType = "time";
  573. axios
  574. .post("/AnalysisMulti/analysis/time", params)
  575. .then((res) => {
  576. const timeListTwo = JSON.parse(res.data);
  577. this.$set(this.fourList[activeIndex], "rowData", currentRow);
  578. this.$set(this.fourList[activeIndex], "timeListTwo", timeListTwo);
  579. })
  580. .catch((error) => {
  581. console.error("Error fetching time domain data:", error);
  582. })
  583. .finally(() => {
  584. this.$set(this.fourList[activeIndex], "loading", false);
  585. });
  586. } else if (type === 2) {
  587. // Type 2: 加载频域数据
  588. this.$set(this.fourList[activeIndex], "loading", true);
  589. params.analysisType = "frequency";
  590. axios
  591. .post("/AnalysisMulti/analysis/frequency", params)
  592. .then((res) => {
  593. const spectrumListTwo = JSON.parse(res.data);
  594. this.$set(this.fourList[activeIndex], "rowData", currentRow);
  595. this.$set(
  596. this.fourList[activeIndex],
  597. "spectrumListTwo",
  598. spectrumListTwo
  599. );
  600. })
  601. .catch((error) => {
  602. console.error("Error fetching frequency domain data:", error);
  603. })
  604. .finally(() => {
  605. this.$set(this.fourList[activeIndex], "loading", false);
  606. });
  607. } else if (type === 3) {
  608. // Type 3: 加载包络分析数据
  609. this.$set(this.fourList[activeIndex], "loading", true);
  610. params.analysisType = "envelope";
  611. params.fmin = this.xiaoval; // 最小频率参数
  612. params.fmax = this.daval; // 最大频率参数
  613. axios
  614. .post("/AnalysisMulti/analysis/envelope", params)
  615. .then((res) => {
  616. const envelopeListTwo = JSON.parse(res.data);
  617. this.$set(this.fourList[activeIndex], "rowData", currentRow);
  618. this.$set(
  619. this.fourList[activeIndex],
  620. "envelopeListTwo",
  621. envelopeListTwo
  622. );
  623. })
  624. .catch((error) => {
  625. console.error("Error fetching envelope analysis data:", error);
  626. })
  627. .finally(() => {
  628. this.$set(this.fourList[activeIndex], "loading", false);
  629. });
  630. } else {
  631. console.warn("Unknown type provided:", type);
  632. }
  633. },
  634. // 下一条数据,向后循环
  635. goToNextRow(type, activeIndex) {
  636. if (this.tableDataList.length === 0) return;
  637. // 更新当前索引
  638. this.currentIndex =
  639. this.currentIndex === this.tableDataList.length - 1
  640. ? 0
  641. : this.currentIndex + 1;
  642. const currentRow = this.tableDataList[this.currentIndex];
  643. this.setCurrent(currentRow);
  644. const params = {
  645. ids: currentRow.id,
  646. // windCode: "SKF001",
  647. windCode: this.companyCode,
  648. };
  649. // 根据type加载不同的数据
  650. if (type === 1) {
  651. // Type 1: 加载时域数据
  652. this.$set(this.fourList[activeIndex], "loading", true);
  653. params.analysisType = "time";
  654. axios
  655. .post("/AnalysisMulti/analysis/time", params)
  656. .then((res) => {
  657. const timeListTwo = JSON.parse(res.data);
  658. this.$set(this.fourList[activeIndex], "rowData", currentRow);
  659. this.$set(this.fourList[activeIndex], "timeListTwo", timeListTwo);
  660. })
  661. .catch((error) => {
  662. console.error("Error fetching time data:", error);
  663. })
  664. .finally(() => {
  665. this.$set(this.fourList[activeIndex], "loading", false);
  666. });
  667. } else if (type === 2) {
  668. // Type 2: 加载频域数据
  669. this.$set(this.fourList[activeIndex], "loading", true);
  670. params.analysisType = "frequency";
  671. axios
  672. .post("/AnalysisMulti/analysis/frequency", params)
  673. .then((res) => {
  674. const spectrumListTwo = JSON.parse(res.data);
  675. this.$set(this.fourList[activeIndex], "rowData", currentRow);
  676. this.$set(
  677. this.fourList[activeIndex],
  678. "spectrumListTwo",
  679. spectrumListTwo
  680. );
  681. })
  682. .catch((error) => {
  683. console.error("Error fetching frequency data:", error);
  684. })
  685. .finally(() => {
  686. this.$set(this.fourList[activeIndex], "loading", false);
  687. });
  688. } else if (type === 3) {
  689. // Type 3: 加载包络分析数据
  690. this.$set(this.fourList[activeIndex], "loading", true);
  691. params.analysisType = "envelope";
  692. params.fmin = this.xiaoval; // 最小频率
  693. params.fmax = this.daval; // 最大频率
  694. axios
  695. .post("/AnalysisMulti/analysis/envelope", params)
  696. .then((res) => {
  697. const envelopeListTwo = JSON.parse(res.data);
  698. this.$set(this.fourList[activeIndex], "rowData", currentRow);
  699. this.$set(
  700. this.fourList[activeIndex],
  701. "envelopeListTwo",
  702. envelopeListTwo
  703. );
  704. })
  705. .catch((error) => {
  706. console.error("Error fetching envelope analysis data:", error);
  707. })
  708. .finally(() => {
  709. this.$set(this.fourList[activeIndex], "loading", false);
  710. });
  711. }
  712. },
  713. // 更新父组件的 currentIndex
  714. handleCurrentIndexUpdate(newIndex) {
  715. this.currentIndex = newIndex;
  716. this.handleCurrentChange(newIndex);
  717. },
  718. tableRowClassName({ row }) {
  719. if (row === this.currentRow) {
  720. return "current-row-highlight"; // 自定义的高亮类名
  721. }
  722. return "";
  723. },
  724. // setCurrent(row) {
  725. // this.currentRow = row; // 设置当前行
  726. // },
  727. // 当前所在行高亮提示
  728. setCurrent(row) {
  729. if (!row) {
  730. return false;
  731. }
  732. this.$refs.singleTable.setCurrentRow(row);
  733. },
  734. // 当前单选
  735. handleCurrentChange(val) {
  736. this.currentRow = val;
  737. const index = this.tableDataList.indexOf(val);
  738. this.currentIndex = index; // 更新当前索引
  739. },
  740. generate(type) {
  741. if (!this.currentRow) {
  742. this.$message.warning("请先选择数据");
  743. return;
  744. }
  745. const nameMap = {
  746. 1: "时域图", // Time Domain Chart
  747. 2: "频谱图", // Spectrogram Chart
  748. 3: "包络谱图", // Envelope Spectrum Chart
  749. };
  750. const chartName = nameMap[type];
  751. if (chartName) {
  752. const newItem = {
  753. name: chartName,
  754. isMinimized: false,
  755. id: `chart-${Date.now()}`,
  756. };
  757. this.fourList.push(newItem);
  758. }
  759. },
  760. tendency() {
  761. if (this.tableDataList.length === 0) {
  762. this.$message.warning("数据为空,无法生成图表");
  763. return;
  764. }
  765. const newItem = {
  766. name: "趋势图",
  767. isMinimized: false,
  768. id: `chart-${Date.now()}`,
  769. };
  770. const params = {
  771. ids: this.tableDataList.map((item) => item.id),
  772. windCode: this.companyCode,
  773. analysisType: "trend",
  774. };
  775. axios
  776. .post("/AnalysisMulti/analysis/trend", params)
  777. .then((res) => {
  778. let jsonStr = res.data;
  779. // ① 仅字符串才处理
  780. if (typeof jsonStr === "string") {
  781. // ② 将 "NaN" 或裸 NaN 替换为 null(更安全的方式)
  782. jsonStr = jsonStr.replace(/\bNaN\b/g, "null"); // 替换裸 NaN
  783. }
  784. // ③ 再解析为对象
  785. this.qsList = JSON.parse(jsonStr);
  786. this.fourList.push(newItem);
  787. })
  788. .catch((error) => {
  789. console.error("趋势图接口报错:", error);
  790. });
  791. },
  792. conditions() {
  793. const params = {
  794. windCode: this.maplist.codeNumber,
  795. windTurbineNumberList: [this.unitvalue],
  796. mesureNameList: [this.monitoringvalue],
  797. startTime: this.$formatDateTWO(this.timevalue[0]),
  798. endTime: this.$formatDateTWO(this.timevalue[1]),
  799. };
  800. const areParamsValid = (params) => {
  801. return (
  802. params.endTime &&
  803. params.startTime &&
  804. params.mesureNameList?.length > 0 &&
  805. params.windCode &&
  806. params.windTurbineNumberList?.length > 0
  807. );
  808. };
  809. if (areParamsValid(params)) {
  810. axios
  811. .post("/ETLapi/waveData/getMesureData", params)
  812. .then((res) => {
  813. this.allTableDataList = res.data.datas || [];
  814. this.handleFakePagination();
  815. })
  816. .catch((error) => {
  817. console.error("Error:", error);
  818. // Handle the error here
  819. });
  820. } else {
  821. this.$message({
  822. message: "请填写全部条件",
  823. type: "warning",
  824. });
  825. }
  826. },
  827. // 缩小
  828. lessen(index) {
  829. if (!this.fourList[index].isMinimized) {
  830. this.fourList[index].isMinimized = true;
  831. }
  832. },
  833. // 放大
  834. amplifier(index) {
  835. const item = this.fourList[index];
  836. if (item.isMinimized) {
  837. item.isMinimized = false;
  838. }
  839. },
  840. // 关闭
  841. close(index) {
  842. this.fourList.splice(index, 1);
  843. },
  844. zhankai() {
  845. this.fourList.forEach((item) => {
  846. item.isMinimized = false;
  847. });
  848. },
  849. suoxiao() {
  850. this.fourList.forEach((item) => {
  851. item.isMinimized = true;
  852. });
  853. },
  854. guanbi() {
  855. this.fourList = [];
  856. },
  857. outputFile() {
  858. var ws1 = XLSX.utils.table_to_book(document.querySelector("#Table1")); //对应要导出的表格id
  859. var wbOut = XLSX.write(ws1, {
  860. bookType: "xlsx",
  861. bookSST: true,
  862. type: "array",
  863. });
  864. try {
  865. FileSaver.saveAs(
  866. new Blob([wbOut], { type: "application/octet-stream" }),
  867. "demo.xlsx"
  868. );
  869. } catch (e) {
  870. if (typeof console !== "undefined") console.log(e, wbOut);
  871. }
  872. return wbOut;
  873. },
  874. handleFakePagination() {
  875. const start = (this.currentPage - 1) * this.pageSize;
  876. const end = start + this.pageSize;
  877. this.tableDataList = this.allTableDataList.slice(start, end);
  878. },
  879. handlePageChange(val) {
  880. this.currentPage = val;
  881. this.handleFakePagination();
  882. },
  883. },
  884. };
  885. </script>
  886. <style lang="scss" scoped>
  887. .head {
  888. // border-top: 5px solid #088080;
  889. // border-bottom: 5px solid #088080;
  890. padding: 5px 0;
  891. display: flex;
  892. justify-content: space-between;
  893. .headleft {
  894. display: flex;
  895. .picture {
  896. cursor: pointer;
  897. display: inline-block;
  898. text-align: center;
  899. margin: 0 20px;
  900. font-size: 12px;
  901. img {
  902. width: 50px;
  903. height: 20px;
  904. }
  905. }
  906. }
  907. .headright {
  908. line-height: 38px;
  909. img {
  910. width: 20px;
  911. height: 20px;
  912. margin: 0 10px;
  913. cursor: pointer;
  914. }
  915. }
  916. }
  917. .searchbox {
  918. display: flex;
  919. margin: 10px 0;
  920. p {
  921. margin-right: 10px;
  922. }
  923. .el-select {
  924. width: 180px;
  925. }
  926. }
  927. .dialog-actions {
  928. text-align: right;
  929. padding: 0 10px;
  930. display: flex;
  931. justify-content: space-between;
  932. position: relative;
  933. }
  934. .subject {
  935. height: 350px;
  936. // overflow: hidden;
  937. // overflow-y: auto;
  938. transition: all 0.3s ease;
  939. padding: 0 10px;
  940. p {
  941. font-size: 10px;
  942. }
  943. }
  944. .main-body {
  945. display: flex;
  946. justify-content: space-between;
  947. align-items: flex-start;
  948. .data-map {
  949. width: 60%;
  950. .chart-area {
  951. margin-bottom: 10px;
  952. box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12), 0 0 6px rgba(0, 0, 0, 0.04);
  953. &:hover {
  954. box-shadow: 0 2px 4px rgb(8, 128, 128, 0.13),
  955. 0 0 6px rgb(8, 128, 128, 0.11);
  956. // border: 1px solid #088080;
  957. }
  958. }
  959. }
  960. .data-map::-webkit-scrollbar {
  961. display: none; /* 隐藏滚动条 */
  962. }
  963. .data-origin {
  964. width: 39%;
  965. box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12), 0 0 6px rgba(0, 0, 0, 0.04);
  966. .pagination-wrapper {
  967. display: flex;
  968. justify-content: center;
  969. margin: 10px 0; /* 可选:分页组件与上方表格的间距 */
  970. }
  971. }
  972. }
  973. .subject.minimized {
  974. height: 0px; /* Adjust height when minimized */
  975. overflow: hidden;
  976. }
  977. // ::v-deep .current-row td {
  978. // background-color: rgba(147, 226, 226, 0.2) !important; /* 高亮的背景颜色 */
  979. // color: #088080;
  980. // font-weight: 600;
  981. // }
  982. .el-input__inner {
  983. width: 340px;
  984. }
  985. </style>