index.vue 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660
  1. <template>
  2. <div class="view-table-content">
  3. <div class="view-dataSpecies-left">
  4. <MenuTree :currentNodeKey="currentNodeKey" nodeKey="id" :treedata="menuTreeData" @TreeNodeclick="treeNodeClick" v-bind="treeObj"> </MenuTree>
  5. </div>
  6. <div class="view-dataSpecies-right">
  7. <div class="view-dataType-title">
  8. <div class="view-dataType-title-btn"></div>
  9. <div class="view-dataType-title-search">
  10. <el-input placeholder="请输入架次号" v-model="keyWordData" class="input1">
  11. <el-button slot="append" icon="el-icon-search" @click="searchClick"></el-button>
  12. </el-input>
  13. </div>
  14. </div>
  15. <div class="view-dataType-table">
  16. <LTable ref="table" @selection-change="selection" :defaultFetch="false" :fetch="fetch" :columns="columns" :dataSource="tableData" :options="options" :pagination="tableRequset"></LTable>
  17. </div>
  18. <!-- 警告列表对话框 -->
  19. <el-dialog :title="dialogTitle" :visible.sync="dialogVisible" :before-close="handleClose" width="1200px">
  20. <el-form ref="form" :inline="true" :model="form" label-width="80px" disabled>
  21. <el-form-item label="编目" prop="aircraftId">
  22. <el-select v-model="form.aircraftId">
  23. <el-option v-for="item in aircaftCatalogAll" :key="item.aircaftCatalogId" :label="item.aircaftCatalogCode" :value="item.aircaftCatalogId"> </el-option>
  24. </el-select>
  25. </el-form-item>
  26. <el-form-item label="架次" prop="sortieNo">
  27. <el-input v-model="form.sortieNo" />
  28. </el-form-item>
  29. <!-- <el-form-item label="飞行时间" prop="flightDate">
  30. <el-input v-model="form.flightDate" />
  31. </el-form-item> -->
  32. </el-form>
  33. <LTable ref="warningTable" @selection-change="selection" :defaultFetch="false" :showColumnSetting="false" :columns="warningColumns" :dataSource="warningTableData" :options="warningOptions" :pagination="warningTableRequset"></LTable>
  34. <el-dialog width="80%" title="飞参数据曲线" :visible.sync="innerVisible" :before-close="innerDialogClose" append-to-body>
  35. <PlayBackChart :chartData="chartData" />
  36. <div style="margin-top: 20px">
  37. <span style="color: #fff; margin-left: 30px">请选择时间区间:</span>
  38. <el-date-picker v-model="mathTime" placement="bottom-start" value-format="yyyy-MM-dd HH:mm:ss.SSS" type="datetimerange" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期" @change="handleMathTime" :clearable="false">
  39. </el-date-picker>
  40. <el-button icon="el-icon-refresh" circle class="refresh" @click="resetTime"></el-button>
  41. <el-button type="success" @click="getExecuteMathAPI" style="margin-left: 15px">确 定</el-button>
  42. <LTable ref="mathTable" :defaultFetch="false" :columns="mathColumns" :dataSource="mathTableData" :options="mathOptions"></LTable>
  43. </div>
  44. <div style="width: 100%; color: #fff; text-align: center">
  45. <el-radio-group class="isFalseAlarm" v-model="isFalseAlarm" size="small">
  46. <el-radio-button label="0">实警</el-radio-button>
  47. <el-radio-button label="1">虚警</el-radio-button>
  48. </el-radio-group>
  49. </div>
  50. <span slot="footer" class="dialog-footer">
  51. <el-button @click="innerDialogClose">取 消</el-button>
  52. <el-button type="primary" @click="submit">确 定</el-button>
  53. </span>
  54. </el-dialog>
  55. </el-dialog>
  56. <el-dialog title="执行进度" :visible.sync="progressVisible" width="800px">
  57. <el-progress :text-inside="true" :stroke-width="24" :percentage="percentage" status="success"></el-progress>
  58. </el-dialog>
  59. </div>
  60. </div>
  61. </template>
  62. <script>
  63. import { getDataImport } from '@/api/als/dataImport'
  64. import { getCurveData, getWarning, updateWarning } from '@/api/als/warning'
  65. import { getAircaftCatalogTree } from '@/api/als/sideTree'
  66. import { getAircaftCatalogAll } from '@/api/als/aircraft'
  67. import PlayBackChart from '@/views/als/components/Charts/playBackChart.vue'
  68. import { deepClone, debounce } from '@/utils/index'
  69. import { executeFalseAlarm, getOssIdDataAPI, executeMath } from '@/api/als/algorithm'
  70. import { getWarningResult, updateWarningResult } from '@/api/als/falseAlarmResult'
  71. export default {
  72. name: 'FalseAlarm',
  73. components: { PlayBackChart },
  74. data() {
  75. // 这里存放数据
  76. return {
  77. dialogTitle: '新增',
  78. dialogVisible: false,
  79. innerVisible: false,
  80. progressVisible: false,
  81. keyWordData: '',
  82. aircaftModelIdList: [],
  83. currentNodeKey: '',
  84. currentNode: {},
  85. menuTreeData: [],
  86. treeObj: {
  87. title: '所属机种',
  88. activityheight: '275px',
  89. searchIcon: false,
  90. configure: {
  91. children: 'children',
  92. label: 'label'
  93. }
  94. },
  95. typeTree: {
  96. children: 'children',
  97. label: 'label'
  98. },
  99. searchValue: '',
  100. columns: [
  101. {
  102. prop: 'aircraftId',
  103. label: '编目',
  104. render: (h, params) => {
  105. const matchedItem = this.aircaftCatalogAll.find((item) => params.row.aircraftId.trim() === item.aircaftCatalogId.trim())
  106. if (matchedItem) {
  107. return h('span', matchedItem.aircaftCatalogCode)
  108. } else {
  109. return h('span', {}, '')
  110. }
  111. }
  112. },
  113. {
  114. prop: 'sortieNo',
  115. label: '架次号'
  116. },
  117. {
  118. prop: 'dataStatus',
  119. label: '状态',
  120. // 1 未处理,2 已处理
  121. render: (h, params) => {
  122. if (params.row.dataStatus == '1') {
  123. return h('span', '未处理')
  124. } else if (params.row.dataStatus == '2') {
  125. return h('span', { class: 'success-state' }, '已处理')
  126. } else {
  127. return h('span', { class: 'warning-state' }, '异常')
  128. }
  129. }
  130. },
  131. {
  132. // 算法执行时间
  133. prop: 'createTime',
  134. label: '创建时间'
  135. },
  136. {
  137. button: true,
  138. label: '操作',
  139. width: '240px',
  140. group: [
  141. {
  142. name: '虚警判断',
  143. type: 'text',
  144. statusKey: 'dataStatus',
  145. disableKey: '2',
  146. round: false,
  147. plain: false,
  148. onClick: (row, index, scope) => {
  149. this.beginExecute(row)
  150. }
  151. },
  152. {
  153. name: '查看',
  154. type: 'text',
  155. statusKey: 'dataStatus',
  156. unDisableKey: '2',
  157. round: false,
  158. plain: false,
  159. onClick: (row, index, scope) => {
  160. this.checkResultList(row)
  161. }
  162. }
  163. ]
  164. }
  165. ],
  166. options: {
  167. stripe: false, // 斑马纹
  168. mutiSelect: true, // 多选框
  169. index: false, // 显示序号, 多选则 mutiSelect
  170. loading: false, // 表格动画
  171. initTable: false, // 是否一挂载就加载数据
  172. border: true,
  173. height: 'calc(100vh - 300px)'
  174. },
  175. tableCheckItems: [],
  176. tableData: [],
  177. tableRequset: {
  178. total: 0,
  179. pageIndex: 1,
  180. pageSize: 20,
  181. searchValue: ''
  182. },
  183. warningColumns: [
  184. {
  185. prop: 'name',
  186. label: '故障名称'
  187. },
  188. {
  189. prop: 'code',
  190. label: 'HMC码'
  191. },
  192. {
  193. prop: 'attribute1',
  194. label: '判据名称',
  195. // render: (h, params) => {
  196. // return h('span', { class: 'warning-state' }, params.row.attribute1)
  197. // },
  198. onClick: (row, index, scope) => {
  199. this.$router.push({ name: 'JudgeFaultLogic' })
  200. }
  201. },
  202. {
  203. prop: 'resultContent',
  204. label: '判断结果',
  205. render: (h, params) => {
  206. if (params.row.resultContent == '0') {
  207. return h('span', { class: 'warning-state' }, '实警')
  208. } else if (params.row.resultContent == '1') {
  209. return h('span', { class: 'success-state' }, '虚警')
  210. } else if (params.row.resultContent == '2') {
  211. return h('span', '判故公式参数不匹配')
  212. } else if (params.row.resultContent == '3') {
  213. return h('span', '该HMC码无判据公式')
  214. }
  215. }
  216. },
  217. {
  218. button: true,
  219. label: '操作',
  220. width: '240px',
  221. group: [
  222. {
  223. name: '查看',
  224. type: 'text',
  225. round: false,
  226. plain: false,
  227. onClick: (row, index, scope) => {
  228. this.checkCurve(row)
  229. }
  230. }
  231. ]
  232. }
  233. ],
  234. warningOptions: {
  235. stripe: false, // 斑马纹
  236. mutiSelect: false, // 多选框
  237. index: true, // 显示序号, 多选则 mutiSelect
  238. loading: false, // 表格动画
  239. initTable: false, // 是否一挂载就加载数据
  240. border: true,
  241. height: 'calc(100vh - 600px)'
  242. },
  243. warningTableCheckItems: [],
  244. warningTableData: [],
  245. warningTableRequset: {
  246. total: 0,
  247. pageIndex: 1,
  248. pageSize: 10,
  249. searchValue: ''
  250. },
  251. mathColumns: [
  252. {
  253. prop: 'params',
  254. label: '参数'
  255. },
  256. {
  257. prop: 'mean',
  258. label: '算数平均数'
  259. },
  260. {
  261. prop: 'variance',
  262. label: '方差'
  263. },
  264. {
  265. prop: 'populationVariance',
  266. label: '总体方差'
  267. },
  268. {
  269. prop: 'sum',
  270. label: '和'
  271. },
  272. {
  273. prop: 'max',
  274. label: '最大值'
  275. },
  276. {
  277. prop: 'min',
  278. label: '最小值'
  279. },
  280. {
  281. prop: 'mode',
  282. label: '众数'
  283. },
  284. {
  285. prop: 'geometricMean',
  286. label: '几何平均数'
  287. },
  288. {
  289. prop: 'sumSq',
  290. label: '平方和'
  291. }
  292. ],
  293. mathOptions: {
  294. stripe: false, // 斑马纹
  295. mutiSelect: false, // 多选框
  296. index: false, // 显示序号, 多选则 mutiSelect
  297. loading: false, // 表格动画
  298. initTable: false, // 是否一挂载就加载数据
  299. border: true,
  300. height: '300px'
  301. },
  302. mathTableData: [],
  303. debounceFn: debounce(this.fetch, 500),
  304. aircaftCatalogAll: [],
  305. chartData: {
  306. title: '',
  307. legendData: [],
  308. xAxisData: [],
  309. yAxisData: [],
  310. seriesData: []
  311. },
  312. form: {
  313. id: '',
  314. sortieNo: '',
  315. aircraftId: '',
  316. ossId: '',
  317. dataStatus: '',
  318. flightDate: ''
  319. },
  320. warningForm: {
  321. id: null,
  322. resultContent: ''
  323. },
  324. isFalseAlarm: '0',
  325. currentSortieNo: '',
  326. percentage: 0,
  327. mathTime: [],
  328. mathParams: {
  329. code: '',
  330. sortieNo: '',
  331. beginTime: '',
  332. endTime: ''
  333. },
  334. backupsTime: []
  335. // startTime:'',
  336. // endTime:'',
  337. }
  338. },
  339. watch: {
  340. keyWord() {
  341. this.tableRequset.pageIndex = 1
  342. this.debounceFn()
  343. }
  344. },
  345. mounted() {
  346. this.getAircaftCatalogTreeAPI()
  347. },
  348. methods: {
  349. async getAircaftCatalogTreeAPI(params) {
  350. try {
  351. const { data } = await getAircaftCatalogTree(params)
  352. this.menuTreeData = data
  353. const getAircaftCatalogAllParams = {
  354. keyWord: '',
  355. aircaftModelIdList: []
  356. }
  357. const { data: data2 } = await getAircaftCatalogAll(getAircaftCatalogAllParams)
  358. this.aircaftCatalogAll = data2
  359. if (data.length) {
  360. this.currentNodeKey = data[0].id
  361. this.currentNode = data[0]
  362. this.aircaftModelIdList = this.getTreeLeafData(data[0]?.children)
  363. .map((e) => e.id)
  364. .toString()
  365. this.getDataImportAPI({ aircraftId: this.aircaftModelIdList })
  366. }
  367. } catch (error) {}
  368. },
  369. getTreeLeafData(list) {
  370. const newArr = []
  371. function getLeaf(data, arr) {
  372. data.forEach((e) => {
  373. if (e.type === 2) {
  374. arr.push(e)
  375. }
  376. if (e.children.length) {
  377. getLeaf(e.children, arr)
  378. }
  379. })
  380. }
  381. getLeaf(list, newArr)
  382. return newArr
  383. },
  384. async getDataImportAPI(params) {
  385. if (this.$refs.table) this.$refs.table.clearSelection()
  386. const { keyWord } = this
  387. const { pageSize, pageIndex } = this.tableRequset
  388. const {
  389. data: { list, total }
  390. } = await getDataImport({ pageSize, pageNum: pageIndex, ...params, source: 1 })
  391. this.tableData = list
  392. this.tableRequset.total = total
  393. },
  394. fetch() {
  395. this.getDataImportAPI({ aircraftId: this.aircaftModelIdList })
  396. },
  397. async searchClick() {
  398. this.getDataImportAPI({ aircraftId: this.aircaftModelIdList, sortieNo: this.keyWordData })
  399. },
  400. treeNodeClick(data) {
  401. this.$refs.table.clearSelection()
  402. this.currentNodeKey = data.id
  403. this.currentNode = data
  404. this.aircaftModelIdList = this.getTreeLeafData(data.children.length ? data.children : [data])
  405. .map((e) => e.id)
  406. .toString()
  407. if (!this.aircaftModelIdList) {
  408. this.aircaftModelIdList = '#'
  409. }
  410. this.getDataImportAPI({ aircraftId: this.aircaftModelIdList })
  411. },
  412. openDialog() {
  413. this.dialogTitle = '虚警抑制结果'
  414. this.dialogVisible = true
  415. },
  416. handleClose() {
  417. this.dialogVisible = false
  418. this.warningTableData = []
  419. this.currentSortieNo = ''
  420. this.form = {
  421. id: '',
  422. sortieNo: '',
  423. aircraftId: '',
  424. ossId: '',
  425. dataStatus: '',
  426. flightDate: ''
  427. }
  428. },
  429. innerDialogClose() {
  430. this.innerVisible = false
  431. this.chartData = {
  432. title: '',
  433. legendData: [],
  434. xAxisData: [],
  435. yAxisData: [],
  436. seriesData: []
  437. }
  438. this.warningForm = {
  439. id: null,
  440. resultContent: ''
  441. }
  442. this.mathParams = {
  443. code: '',
  444. sortieNo: '',
  445. beginTime: '',
  446. endTime: ''
  447. }
  448. this.mathTableData = []
  449. this.isFalseAlarm = false
  450. },
  451. submit() {
  452. this.warningForm.resultContent = this.isFalseAlarm
  453. this.updateWarningResultAPI()
  454. },
  455. async updateWarningResultAPI() {
  456. try {
  457. const { code } = await updateWarningResult({ ...this.warningForm })
  458. if (code === 200) {
  459. this.$message({
  460. type: 'success',
  461. message: '操作成功!'
  462. })
  463. this.innerDialogClose()
  464. this.getWarningResultAPI({ sortieNo: this.currentSortieNo })
  465. }
  466. } catch (error) {}
  467. },
  468. selection(val) {
  469. this.tableCheckItems = val
  470. },
  471. checkResultList(row) {
  472. this.currentSortieNo = this.form.sortieNo = row.sortieNo
  473. this.form.aircraftId = row.aircraftId
  474. this.form.flightDate = row.flightDate
  475. this.getWarningResultAPI({ sortieNo: row.sortieNo })
  476. this.openDialog()
  477. },
  478. async getWarningResultAPI(params) {
  479. if (this.$refs.warningTable) this.$refs.warningTable.clearSelection()
  480. const { pageSize, pageIndex } = this.warningTableRequset
  481. const {
  482. data: { list, total }
  483. } = await getWarningResult({ pageSize, pageNum: pageIndex, ...params })
  484. this.warningTableData = list
  485. this.warningTableRequset.total = total
  486. },
  487. async getWarningAPI(params) {
  488. if (this.$refs.warningTable) this.$refs.warningTable.clearSelection()
  489. const { pageSize, pageIndex } = this.warningTableRequset
  490. const {
  491. data: { list, total }
  492. } = await getWarning({ pageSize, pageNum: pageIndex, ...params })
  493. this.warningTableData = list
  494. this.warningTableRequset.total = total
  495. },
  496. async checkCurve(row) {
  497. this.isFalseAlarm = row.resultContent
  498. this.warningForm = deepClone(row)
  499. this.mathParams.code = row.code
  500. this.mathParams.sortieNo = row.sortieNo
  501. this.getExecuteMathAPI()
  502. try {
  503. const { code, data } = await getCurveData(row.code, row.sortieNo)
  504. if (code === 200) {
  505. if (data) {
  506. this.getResultData(data)
  507. } else {
  508. this.$message({
  509. type: 'warning',
  510. message: '无飞参数据!'
  511. })
  512. }
  513. }
  514. } catch (error) {}
  515. },
  516. handleMathTime(time) {
  517. this.mathParams.beginTime = time[0]
  518. this.mathParams.endTime = time[1]
  519. },
  520. resetTime() {
  521. this.mathTime = this.backupsTime
  522. },
  523. // 获取数学数据
  524. async getExecuteMathAPI() {
  525. try {
  526. const { data, code } = await executeMath(this.mathParams)
  527. if (code === 200) {
  528. this.mathTableData = []
  529. Object.keys(data).forEach((item) => {
  530. this.mathTableData.push({
  531. params: item,
  532. ...data[item]
  533. })
  534. })
  535. }
  536. } catch (error) {}
  537. },
  538. getResultData(data) {
  539. this.chartData = {
  540. title: '',
  541. legendData: [],
  542. xAxisData: [],
  543. yAxisData: [],
  544. seriesData: []
  545. }
  546. // const { contentData, headData } = this.handleResultData(JSON.parse(data))
  547. const contentData = JSON.parse(data)
  548. const headData = Object.keys(contentData)
  549. this.chartData.legendData = headData
  550. for (var key in contentData) {
  551. if (key === '时间') {
  552. const timeList = contentData['时间']
  553. const time = [timeList[0], timeList[timeList.length - 1]]
  554. this.mathTime = this.backupsTime = time
  555. this.chartData.xAxisData = timeList
  556. } else {
  557. this.chartData.seriesData.push({
  558. name: key,
  559. type: 'line',
  560. data: contentData[key],
  561. connectNulls: true
  562. })
  563. }
  564. }
  565. this.innerVisible = true
  566. },
  567. handleResultData(resultData) {
  568. const headData = Object.keys(resultData)
  569. const contentData = {}
  570. headData.forEach((headItem) => {
  571. contentData[headItem] = []
  572. })
  573. resultData.forEach((item) => {
  574. for (var key in item) {
  575. contentData[key].push(item[key])
  576. }
  577. })
  578. return { contentData, headData }
  579. },
  580. async beginExecute(row) {
  581. this.form = deepClone(row)
  582. this.progressVisible = true
  583. let myTimer = setInterval(() => {
  584. if (this.percentage < 100) {
  585. if (this.percentage === 99) {
  586. this.percentage = 99
  587. } else {
  588. this.percentage += 1
  589. }
  590. }
  591. }, 30)
  592. try {
  593. this.form.dataId = row.id
  594. const res = await executeFalseAlarm(this.form)
  595. clearInterval(myTimer)
  596. if (res?.code === 200) {
  597. this.handleClose()
  598. this.$message({
  599. type: 'success',
  600. message: '执行成功!'
  601. })
  602. // const res = await getWarningResult({ falseAlarmId: row.sortieNo })
  603. // const { data } = await getListByIdsApi(JSON.parse(res.data).ossId)
  604. // this.resultShowData.url = data[0].url
  605. this.checkResultList(row)
  606. this.dialogVisible = true
  607. this.getDataImportAPI({ aircraftId: this.aircaftModelIdList })
  608. }
  609. } catch (error) {
  610. clearInterval(myTimer)
  611. } finally {
  612. this.progressVisible = false
  613. this.percentage = 0
  614. }
  615. }
  616. }
  617. }
  618. </script>
  619. <style lang="scss" scoped>
  620. @import '../index.scss';
  621. .isFalseAlarm {
  622. // position: absolute;
  623. // right: 20px;
  624. margin-top: 20px;
  625. color: #fff;
  626. z-index: 9999;
  627. }
  628. .refresh {
  629. padding: 5px !important;
  630. border-radius: 50% !important;
  631. margin-left: 10px;
  632. }
  633. </style>