spectrogramcharts.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521
  1. <template>
  2. <div>
  3. <div class="FD">
  4. <!-- 光标 -->
  5. <div v-if="BGshow" class="eigenvalue">
  6. <el-checkbox-group v-model="checkedGB">
  7. <el-checkbox v-for="(item, index) in GBcheckList" :key="index" :label="item.val">
  8. {{ item.val }}
  9. </el-checkbox>
  10. </el-checkbox-group>
  11. </div>
  12. <!-- 特征值 -->
  13. <div v-if="PXshow" class="eigenvalue">
  14. <el-checkbox-group v-model="checkedValues" @change="handleCheckChange">
  15. <el-checkbox v-for="(item, index) in PXcheckList" :key="index" :label="item.val">
  16. {{ item.val }}
  17. </el-checkbox>
  18. </el-checkbox-group>
  19. </div>
  20. </div>
  21. <!-- ECharts 图表容器 -->
  22. <div class="line-chart" ref="chart"></div>
  23. </div>
  24. </template>
  25. <script>
  26. import axios from "axios";
  27. import * as echarts from "echarts"; // 导入 echarts 库
  28. export default {
  29. name: "TimedomainCharts", // 组件名称
  30. props: {
  31. currentIndex: {
  32. type: Number,
  33. default: 0,
  34. },
  35. activeIndex: {
  36. type: Number,
  37. default: 0,
  38. },
  39. ids: {
  40. type: Array,
  41. default: () => [],
  42. },
  43. spectrumListTwo: {
  44. type: Object,
  45. default: () => ({}),
  46. },
  47. currentRow: {
  48. type: Object,
  49. default: () => ({}),
  50. },
  51. windCode: {
  52. type: String,
  53. default: "",
  54. },
  55. },
  56. data() {
  57. return {
  58. chartInstance: null,
  59. option: null,
  60. TZshow: false,
  61. BGshow: false,
  62. PXshow: false,
  63. spectrumList: {},
  64. GBcheckList: [
  65. { val: "添加光标" },
  66. { val: "谐波光标" },
  67. { val: "边带光标" },
  68. { val: "移动峰值" },
  69. ],
  70. PXcheckList: [
  71. { val: "Fr", checked: false },
  72. { val: "BPFI", checked: false },
  73. { val: "BPFO", checked: false },
  74. { val: "BSF", checked: false },
  75. { val: "FTF", checked: false },
  76. { val: "3P", checked: false },
  77. ],
  78. Fr: [],
  79. BPFI: [],
  80. BPFO: [],
  81. BSF: [],
  82. FTF: [],
  83. B3P: [],
  84. checkedGB: [],
  85. checkedValues: [],
  86. };
  87. },
  88. watch: {
  89. // 监听 chartData 和 chartLabels 的变化,重新绘制图表
  90. chartData(newData) {
  91. this.updateChart(newData, this.chartLabels);
  92. },
  93. chartLabels(newLabels) {
  94. this.updateChart(this.chartData, newLabels);
  95. },
  96. spectrumListTwo(newValue) {
  97. this.spectrumList = newValue; // 将 spectrumListTwo 的新值赋给 spectrumList
  98. if (this.chartInstance) {
  99. this.updateChart(this.spectrumList.y, this.spectrumList.x); // 更新图表
  100. }
  101. },
  102. spectrumList: {
  103. handler(newValue) {
  104. if (!newValue) return;
  105. console.log(newValue, "newValue");
  106. if (this.chartInstance) {
  107. this.updateChart(newValue.y, newValue.x); // 只在 chartInstance 初始化后更新图表
  108. }
  109. },
  110. deep: true, // 深度监听
  111. },
  112. },
  113. mounted() {
  114. this.$nextTick(() => {
  115. setTimeout(() => {
  116. this.initializeChart(); // 延迟2秒后调用
  117. this.getTime();
  118. }, 500); // 500毫秒,即0.5秒
  119. });
  120. },
  121. methods: {
  122. initializeChart() {
  123. const chartDom = this.$refs.chart;
  124. if (chartDom && !this.chartInstance) {
  125. this.chartInstance = echarts.init(chartDom); // 仅初始化一次
  126. }
  127. // 使用 $nextTick 确保数据更新后再渲染图表
  128. this.$nextTick(() => {
  129. if (this.chartInstance && this.spectrumList.y && this.spectrumList.x) {
  130. this.updateChart(this.spectrumList.y, this.spectrumList.x); // 更新图表
  131. }
  132. });
  133. },
  134. // 更新图表数据
  135. updateChart(data, labels) {
  136. if (
  137. !this.chartInstance ||
  138. !Array.isArray(labels) ||
  139. !Array.isArray(data) ||
  140. labels.length !== data.length
  141. ) {
  142. console.error("Invalid data or labels");
  143. return;
  144. }
  145. const createMarkLine = (dataSource, color) => ({
  146. type: "line",
  147. markLine: {
  148. silent: false,
  149. lineStyle: { color, type: "solid", width: 2 },
  150. symbol: ["arrow", "none"],
  151. label: {
  152. show: true,
  153. position: "end",
  154. formatter: ({ data }) => data.val,
  155. },
  156. emphasis: {
  157. lineStyle: { color: "#FF6A00", width: 4 },
  158. label: {
  159. show: true,
  160. formatter: ({ value }) => `特征值: ${value}`,
  161. color: "#000",
  162. backgroundColor: "#FFF",
  163. padding: [2, 4],
  164. borderRadius: 3,
  165. fontSize: 12,
  166. },
  167. },
  168. data: dataSource.map(({ Xaxis, val }) => ({ xAxis: Xaxis, val })),
  169. },
  170. });
  171. const markLines = [
  172. { data: this.Fr, color: "#A633FF" },
  173. { data: this.BPFI, color: "#23357e" },
  174. { data: this.BPFO, color: "#42a0ae" },
  175. { data: this.BSF, color: "#008080" },
  176. { data: this.FTF, color: "#af254f" },
  177. { data: this.B3P, color: "#FFD700" },
  178. ].map(({ data, color }) => createMarkLine(data, color));
  179. const option = {
  180. title: { text: this.spectrumList.title, left: "center" },
  181. toolbox: {
  182. feature: {
  183. dataZoom: { yAxisIndex: "none" },
  184. restore: {},
  185. saveAsImage: {},
  186. myCustomTool: {
  187. show: true,
  188. title: "上一条",
  189. icon: `image://${require("@/assets/analyse/08.png")}`,
  190. onclick: () => this.previousRow(),
  191. },
  192. myCustomTool2: {
  193. show: true,
  194. title: "下一条",
  195. icon: `image://${require("@/assets/analyse/09.png")}`,
  196. onclick: () => this.nextRow(),
  197. },
  198. myCustomTool4: {
  199. show: true,
  200. title: "光标",
  201. icon: `image://${require("@/assets/analyse/12.png")}`,
  202. onclick: () => this.Show("2"),
  203. },
  204. myCustomTool5: {
  205. show: true,
  206. title: "特征频率",
  207. icon: `image://${require("@/assets/analyse/13.png")}`,
  208. onclick: () => this.Show("3"),
  209. },
  210. },
  211. },
  212. xAxis: {
  213. type: "value",
  214. name: this.spectrumList.xaxis,
  215. nameLocation: "center",
  216. nameTextStyle: {
  217. fontSize: 14,
  218. color: "#333",
  219. padding: [10, 0, 0, 0],
  220. },
  221. },
  222. yAxis: {
  223. type: "value",
  224. name: this.spectrumList.yaxis,
  225. nameTextStyle: {
  226. fontSize: 14,
  227. color: "#333",
  228. padding: [10, 0, 0, 0],
  229. },
  230. },
  231. tooltip: {
  232. trigger: "axis",
  233. formatter: ([
  234. {
  235. value: [x, y],
  236. },
  237. ]) => `X: ${x}<br/>Y: ${y}`,
  238. axisPointer: { type: "line" },
  239. },
  240. dataZoom: [
  241. { type: "inside", start: 0, end: 10 },
  242. {
  243. type: "slider",
  244. start: 0,
  245. end: 10,
  246. handleSize: "80%",
  247. showDataShadow: false,
  248. },
  249. ],
  250. series: [
  251. {
  252. name: "数据系列",
  253. type: "line",
  254. data: labels.map((x, i) => [x, data[i]]),
  255. symbol: "none",
  256. lineStyle: { color: "#162961", width: 1 },
  257. itemStyle: {
  258. color: "#162961",
  259. borderColor: "#fff",
  260. borderWidth: 1,
  261. },
  262. large: true,
  263. progressive: 2000,
  264. },
  265. ...markLines,
  266. ],
  267. };
  268. this.chartInstance.setOption(option);
  269. },
  270. handleCheckChange() {
  271. this.PXcheckList.forEach((item) => {
  272. item.checked = this.checkedValues.includes(item.val);
  273. });
  274. // 构建新的特征频率数据
  275. const newFeatureLines = {
  276. Fr: this.checkedValues.includes("Fr") ? this.spectrumList.fn_Gen : [],
  277. BPFI: this.checkedValues.includes("BPFI") ? this.spectrumList.BPFI : [],
  278. BPFO: this.checkedValues.includes("BPFO") ? this.spectrumList.BPFO : [],
  279. BSF: this.checkedValues.includes("BSF") ? this.spectrumList.BSF : [],
  280. FTF: this.checkedValues.includes("FTF") ? this.spectrumList.FTF : [],
  281. B3P: this.checkedValues.includes("3P")
  282. ? Array.isArray(this.spectrumList.B3P)
  283. ? this.spectrumList.B3P
  284. : [{ Xaxis: this.spectrumList.B3P, val: "3P" }]
  285. : [],
  286. };
  287. // 仅更新 `series`,避免重新渲染整个 ECharts 组件
  288. if (this.chartInstance) {
  289. this.chartInstance.setOption(
  290. {
  291. series: this.generateSeries(newFeatureLines),
  292. },
  293. { replaceMerge: ["series"] }
  294. );
  295. }
  296. },
  297. generateSeries(featureLines) {
  298. const createMarkLine = (dataSource, color) => ({
  299. type: "line",
  300. markLine: {
  301. silent: false,
  302. lineStyle: { color, type: "dashed", width:1 },
  303. symbol: ["arrow", "none"],
  304. label: {
  305. show: true,
  306. position: "end",
  307. formatter: ({ data }) => data.val,
  308. },
  309. emphasis: {
  310. lineStyle: { color: "#FF6A00", width: 2 },
  311. label: {
  312. show: true,
  313. formatter: ({ value }) => `特征值: ${value}`,
  314. color: "#000",
  315. },
  316. },
  317. data: dataSource.map(({ Xaxis, val }) => ({ xAxis: Xaxis, val })),
  318. },
  319. });
  320. const markLines = [
  321. { data: featureLines.Fr, color: "#A633FF" },
  322. { data: featureLines.BPFI, color: "#23357e" },
  323. { data: featureLines.BPFO, color: "#42a0ae" },
  324. { data: featureLines.BSF, color: "#008080" },
  325. { data: featureLines.FTF, color: "#af254f" },
  326. { data: featureLines.B3P, color: "#FFD700" },
  327. ].map(({ data, color }) => createMarkLine(data, color));
  328. return [
  329. {
  330. name: "数据系列",
  331. type: "line",
  332. data: this.spectrumList.x.map((x, i) => [x, this.spectrumList.y[i]]),
  333. symbol: "none",
  334. lineStyle: { color: "#162961", width: 1 },
  335. itemStyle: { color: "#162961", borderColor: "#fff", borderWidth: 1 },
  336. large: true,
  337. },
  338. ...markLines,
  339. ];
  340. },
  341. getTime() {
  342. this.$emit("handleLoading", null, true, this.activeIndex);
  343. const params = {
  344. ids: this.ids,
  345. windCode: this.windCode,
  346. analysisType: "frequency",
  347. };
  348. axios
  349. .post("/WJapi/analysis/frequency", params)
  350. .then((res) => {
  351. console.log(res, "频谱图数据");
  352. this.spectrumList = { ...JSON.parse(res.data) };
  353. console.log(this.spectrumList, "频谱图数据1");
  354. const XrmsValue = this.spectrumList?.Xrms;
  355. // 通过 $emit 传递 XrmsValue 给父组件
  356. this.$emit("updateXrms", XrmsValue);
  357. this.PXcheckList.forEach((item) => {
  358. if (item.checked) {
  359. switch (item.val) {
  360. case "Fr":
  361. this.Fr = this.spectrumList.fn_Gen;
  362. break;
  363. case "BPFI":
  364. this.BPFI = this.spectrumList.BPFI;
  365. break;
  366. case "BPFO":
  367. this.BPFO = this.spectrumList.BPFO;
  368. break;
  369. case "BSF":
  370. this.BSF = this.spectrumList.BSF;
  371. break;
  372. case "FTF":
  373. this.FTF = this.spectrumList.FTF;
  374. break;
  375. case "3P":
  376. this.B3P = Array.isArray(this.spectrumList.B3P)
  377. ? this.spectrumList.B3P
  378. : [{ Xaxis: this.spectrumList.B3P, val: "3P" }];
  379. break;
  380. default:
  381. break;
  382. }
  383. }
  384. });
  385. })
  386. .catch((error) => {
  387. console.error(error);
  388. })
  389. .finally(() => {
  390. this.$emit("handleLoading", this.currentRow, false, this.activeIndex);
  391. });
  392. },
  393. previousRow() {
  394. this.$emit("update-previous-row", 2, this.activeIndex);
  395. },
  396. nextRow() {
  397. this.$emit("update-next-row", 2, this.activeIndex);
  398. },
  399. Show(value) {
  400. const stateMap = {
  401. 1: { TZshow: true, BGshow: false, PXshow: false },
  402. 2: { TZshow: false, BGshow: true, PXshow: false },
  403. 3: { TZshow: false, BGshow: false, PXshow: true },
  404. };
  405. if (stateMap[value]) {
  406. // Toggle the state for the given value
  407. this.TZshow = value === "1" ? !this.TZshow : false;
  408. this.BGshow = value === "2" ? !this.BGshow : false;
  409. this.PXshow = value === "3" ? !this.PXshow : false;
  410. }
  411. },
  412. // handleCheckChange() {
  413. // this.PXcheckList.forEach((item) => {
  414. // // 如果 `checkedValues` 里有这个项,则 checked=true,否则 checked=false
  415. // item.checked = this.checkedValues.includes(item.val);
  416. // });
  417. // // 重置数据数组
  418. // this.Fr = [];
  419. // this.BPFI = [];
  420. // this.BPFO = [];
  421. // this.BSF = [];
  422. // this.FTF = [];
  423. // this.B3P = [];
  424. // // 找到刚刚被点击的项
  425. // const changedItem = this.PXcheckList.find(
  426. // (item) => !this.checkedValues.includes(item.val) !== item.checked
  427. // );
  428. // if (changedItem) {
  429. // console.log("当前点击项:", changedItem);
  430. // // 根据选中状态赋值
  431. // if (this.checkedValues.includes("Fr")) {
  432. // this.Fr = this.spectrumList.fn_Gen;
  433. // }
  434. // if (this.checkedValues.includes("BPFI")) {
  435. // this.BPFI = this.spectrumList.BPFI;
  436. // }
  437. // if (this.checkedValues.includes("BPFO")) {
  438. // this.BPFO = this.spectrumList.BPFO;
  439. // }
  440. // if (this.checkedValues.includes("BSF")) {
  441. // this.BSF = this.spectrumList.BSF;
  442. // }
  443. // if (this.checkedValues.includes("FTF")) {
  444. // this.FTF = this.spectrumList.FTF;
  445. // }
  446. // if (this.checkedValues.includes("3P")) {
  447. // this.B3P = Array.isArray(this.spectrumList.B3P)
  448. // ? this.spectrumList.B3P
  449. // : [{ Xaxis: this.spectrumList.B3P, val: "3P" }];
  450. // }
  451. // // 更新 ECharts 图表数据
  452. // if (this.chartInstance) {
  453. // this.updateChart(this.spectrumList.y, this.spectrumList.x);
  454. // }
  455. // }
  456. // },
  457. },
  458. };
  459. </script>
  460. <style lang="scss" scoped>
  461. .line-chart {
  462. width: 100%;
  463. height: 280px;
  464. }
  465. .FD {
  466. width: 100%;
  467. height: 1px;
  468. position: relative;
  469. }
  470. .eigenvalue {
  471. position: absolute;
  472. top: 30px;
  473. right: 0;
  474. font-size: 10px;
  475. width: 100px;
  476. border: 1px solid black;
  477. padding: 5px;
  478. background: #fff;
  479. z-index: 99;
  480. h5 {
  481. line-height: 16px;
  482. height: 16px;
  483. }
  484. }
  485. </style>