index.vue 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559
  1. <template>
  2. <div>
  3. <div class="myCarousel">
  4. <span>{{ text }}</span>
  5. </div>
  6. <div class="condition">
  7. <div class="conditionOne">
  8. <span>测风塔:</span>
  9. <el-select v-model="cftId" placeholder="请选择" @change="changeCft" size="small" style="width: 170px">
  10. <el-option
  11. v-for="item in startDateAndEndDate"
  12. :key="item.value"
  13. :label="item.label"
  14. :value="item.value">
  15. <span style="float: left;">{{ item.label }}</span>
  16. <span style="float: right; color: #8492a6; font-size: 13px">{{ item.date }}</span>
  17. </el-option>
  18. </el-select>
  19. </div>
  20. <div class="conditionTwo">
  21. <span>时间:</span>
  22. <el-date-picker
  23. v-model="dataTime"
  24. type="monthrange"
  25. range-separator="至"
  26. start-placeholder="开始日期"
  27. end-placeholder="结束日期"
  28. @change="changeMonth"
  29. :picker-options="pickerOptions"
  30. style="width: 200px"
  31. size="small"
  32. >
  33. </el-date-picker>
  34. </div>
  35. <!-- <div class="conditionTwo">-->
  36. <!-- <span>层高:</span>-->
  37. <!-- <el-select v-model="height" placeholder="请选择" clearable size="small" style="width: 150px">-->
  38. <!-- <el-option-->
  39. <!-- v-for="item in options"-->
  40. <!-- :key="item.value"-->
  41. <!-- :label="item.label"-->
  42. <!-- :value="item.value">-->
  43. <!-- </el-option>-->
  44. <!-- </el-select>-->
  45. <!-- </div>-->
  46. <el-button class="seachBtu" type="primary" plain icon="el-icon-thumb" :loading="loading" size="mini"
  47. @click="getPdfData()">生成报告模板
  48. </el-button>
  49. <el-button class="seachBtu" type="primary" plain icon="el-icon-download" :loading="downLoading" size="mini"
  50. @click="getPdf()">导出
  51. </el-button>
  52. </div>
  53. <div id="dataAnalysisPdf" v-loading="loading">
  54. <pdf-home-page :param="info"/>
  55. <!--pdf主体-->
  56. <div style="width: 90%;margin: 0 auto">
  57. <div style="height: 2220px">
  58. <!-- 1项目综述和概况 -->
  59. <div>
  60. <h1>1.项目综述和概况</h1>
  61. <h2>1.1 项目综述</h2>
  62. <div><span class="text">测风设备部分参数统计结果如下表所示。</span></div>
  63. <div class="pdfTableDiv" style="width: 50%;">
  64. <div class="tableTitle"><span>表1 测风设备主要参数表</span></div>
  65. <div class="descriptionsDiv" style="font-size: 20px">
  66. <el-descriptions class="margin-top" :column="1" border>
  67. <el-descriptions-item>
  68. <template slot="label">测风设备命名</template>
  69. {{ windTowerInfo.name }}
  70. </el-descriptions-item>
  71. <el-descriptions-item>
  72. <template slot="label">仪器编号</template>
  73. {{ windTowerInfo.equipmentNo }}
  74. </el-descriptions-item>
  75. <el-descriptions-item>
  76. <template slot="label">安装完成时间</template>
  77. {{ windTowerInfo.installationTime }}
  78. </el-descriptions-item>
  79. <el-descriptions-item>
  80. <template slot="label">数据起时间</template>
  81. {{ windTowerInfo.startTime }}
  82. </el-descriptions-item>
  83. <el-descriptions-item>
  84. <template slot="label">数据止时间</template>
  85. {{ windTowerInfo.endTime }}
  86. </el-descriptions-item>
  87. </el-descriptions>
  88. </div>
  89. </div>
  90. </div>
  91. <!-- 2.测风数据分析 -->
  92. <div>
  93. <h1>2.测风数据分析</h1>
  94. <h2>2.1气象要素分析</h2>
  95. <div><span class="text">具体测风设备相关信息及位置分布如下所示。</span></div>
  96. <div class="pdfTableDiv">
  97. <div class="tableTitle"><span>表2 测风基本信息</span></div>
  98. <div class="rowDiv">
  99. <div>
  100. <el-table
  101. :show-header="false" :span-method="arraySpanMethod"
  102. :data="tableData"
  103. border
  104. class="pdfTable">
  105. <el-table-column
  106. prop="name" align="center"
  107. label="日期"
  108. width="180">
  109. </el-table-column>
  110. <el-table-column
  111. prop="column" align="center"
  112. label="日期"
  113. width="180">
  114. </el-table-column>
  115. </el-table>
  116. </div>
  117. <div style="width: 40%">
  118. <el-row>
  119. <el-col class="tableCol">{{ windTowerInfo.name }}</el-col>
  120. <el-col class="tableCol">{{ windTowerInfo.equipmentNo }}</el-col>
  121. <el-col class="tableCol">{{ windTowerInfo.longitude }}</el-col>
  122. <el-col class="tableCol">{{ windTowerInfo.latitude }}</el-col>
  123. <el-col class="tableCol">{{ windTowerInfo.wsHeight }}</el-col>
  124. <el-col class="tableCol">{{ windTowerInfo.wdHeight }}</el-col>
  125. </el-row>
  126. </div>
  127. </div>
  128. </div>
  129. </div>
  130. <!-- 2.2数据完整性 -->
  131. <div>
  132. <h2>2.2 数据完整性</h2>
  133. <div><span class="text">自{{ dataIntegrity.time }}起测风设备安装完毕,{{
  134. dataIntegrity.startTime
  135. }}起均正常存取数据。数据总条数为{{ dataIntegrity.totalNum }},测风数据完整率
  136. {{ dataIntegrity.integrityRate }}%。</span></div>
  137. </div>
  138. <div>
  139. <h2>2.3 风能要素</h2>
  140. <h3>2.3.1 空气密度</h3>
  141. <div style="line-height: 30px">
  142. <div><span class="text">由于空气密度直接影响风能的大小,在同等风速条件下,空气密度越大风能越大;根据风电场测风塔的实测温度和气压数据推算测风塔处空气密度计算公式如下:</span>
  143. </div>
  144. <div><span class="text">ρ=P/(R*T)</span>
  145. </div>
  146. <div><span class="text">其中:</span>
  147. </div>
  148. <div><span class="text">ρ为空气密度(kg/m3);</span>
  149. </div>
  150. <div><span class="text">P为平均大气压(Pa);</span>
  151. </div>
  152. <div><span class="text">R为空气常数(287J/kg*K);</span>
  153. </div>
  154. <div><span class="text">T为绝对温度(℃+273)</span>
  155. </div>
  156. </div>
  157. <div class="pdfTableDiv">
  158. <div class="tableTitle"><span>表3 {{ windTowerInfo.name }}测风设备温湿压六要素/空气密度统计结果</span></div>
  159. <div class="rowDiv" style="width: 60%;margin: 0 auto;">
  160. <el-table
  161. :data="envTableData"
  162. border
  163. :header-row-style="{color: '#000'}"
  164. class="pdfTable" style="border: 1px solid #000">
  165. <el-table-column prop="parameter" align="center" label="参数"></el-table-column>
  166. <el-table-column prop="ave" align="center" label="平均值"></el-table-column>
  167. <el-table-column prop="max" align="center" label="最大值"></el-table-column>
  168. <el-table-column prop="min" align="center" label="最小值"></el-table-column>
  169. </el-table>
  170. </div>
  171. </div>
  172. </div>
  173. </div>
  174. <ws-and-wd :info="windTowerInfo" :pData="wsAndwd"/>
  175. <wd-rose :info="windTowerInfo" :pData="roseData"/>
  176. <ws-frequency :p-data="weibull"/>
  177. <turbulence style="height: 2220px" :p-data="turbulenceData"/>
  178. <wind-shear style="height: 2220px" :pData="shearData"/>
  179. </div>
  180. </div>
  181. </div>
  182. </template>
  183. <script>
  184. import pdfHomePage from './pdfHomePage'
  185. import wsAndWd from './components/wsAndWpd'
  186. import wdRose from './components/wdRose'
  187. import windShear from './components/windShear'
  188. import wsFrequency from './components/wsFrequency'
  189. import turbulence from './components/turbulence'
  190. import {listEquipmentIdAndDataTime} from "@/api/biz/dataQuery/windTowerStatusInfo";
  191. import {getDataTimeForEveryTower,generatePDF} from "@/api/biz/dataQuery/pdf";
  192. import defaultOption from "@/api/biz/dataQuery/defaultOption";
  193. import WsFrequency from "@/views/dataAnalysis/components/wsFrequency";
  194. import htmlToPdf from "@/utils/htmlToPdf";
  195. import Cookies from "js-cookie";
  196. export default {
  197. name: "index",
  198. components: {WsFrequency, pdfHomePage, wsAndWd, wdRose, windShear, wsFrequency, turbulence},
  199. data() {
  200. return {
  201. loading: false,
  202. downLoading: false,
  203. text: '**** 生成pdf报告流程: 1.选择测风塔和层高 2.生成报告模板 3.导出 ****',
  204. cftId: '',
  205. pdfData:[],
  206. intervalID: null,
  207. startDateAndEndDate: [],
  208. dataTime: [],
  209. pickerMinDate: null,
  210. pickerMaxDate: null,
  211. pickerOptions: {
  212. //点击时间回调
  213. onPick: ({maxDate, minDate}) => {
  214. if (minDate) {
  215. let currentYear = minDate.getMonth()
  216. this.pickerMinDate = new Date(minDate).setMonth(currentYear - 11)
  217. this.pickerMaxDate = new Date(minDate).setMonth(currentYear + 11)
  218. }
  219. },
  220. //禁用时间 打开选择器就调用
  221. disabledDate: (time) => {
  222. if (this.pickerMinDate != null) {
  223. //点击月份后只允许选前后1年的时间
  224. //return true是禁用
  225. return time.getTime() < this.pickerMinDate || this.pickerMaxDate < time.getTime()
  226. }
  227. },
  228. },
  229. height: '',
  230. options: [],
  231. allOptions: [],
  232. /*pdf数据*/
  233. info: {equipmentId: '声雷达6172'},
  234. /*测风塔基本信息*/
  235. windTowerInfo: {},
  236. tableData: [
  237. {name: "测风设备命名", column: 0},
  238. {name: "仪器编号", column: 0},
  239. {name: "地理位置", column: '经度'},
  240. {name: "地理位置", column: '纬度'},
  241. {name: "通道信息", column: '风速高度(m)'},
  242. {name: "通道信息", column: '风向高度(m)'},
  243. ],
  244. /*数据完整性*/
  245. dataIntegrity: {},
  246. /*环境数据*/
  247. envTableData: [],
  248. wsAndwd:{},
  249. roseData:[],
  250. weibull:[],
  251. turbulenceData:[],
  252. shearData: {},
  253. defaultTimeData: [],//默认时间范围集合
  254. }
  255. },
  256. destroyed() {
  257. clearInterval(this.intervalID)
  258. this.intervalID = null
  259. },
  260. mounted() {
  261. this.allOptions = defaultOption.allHeightOptions
  262. this.getlistEquipmentIdAndDataTime()
  263. },
  264. methods: {
  265. getlistEquipmentIdAndDataTime() {
  266. // this.changeMonth(this.dataTime)
  267. /*简易走马灯*/
  268. if (this.intervalID != null) return;
  269. this.intervalID = setInterval(() => {
  270. var start = this.text.substring(0, 1)
  271. var end = this.text.substring(1)
  272. this.text = end + start
  273. }, 400)
  274. /*****/
  275. listEquipmentIdAndDataTime().then(res => {
  276. this.startDateAndEndDate = res.data
  277. this.cftId = res.data[0].value
  278. // this.changeHeight(res.data[0])
  279. })
  280. /*****/
  281. getDataTimeForEveryTower().then(res => {
  282. this.defaultTimeData = res.data
  283. let startAndEndTime = this.defaultTimeData.find(w => w.eqId == this.cftId)
  284. this.dataTime = [startAndEndTime.startTime, startAndEndTime.endTime]
  285. }).catch(err => {
  286. console.log('获取所有测风塔的开始结束时间异常:' + err)
  287. })
  288. },
  289. /*pdf查询*/
  290. getPdfData(){
  291. this.loading = true
  292. this.downLoading = true
  293. generatePDF({
  294. equipmentId: this.cftId,
  295. startDay: new Date(this.dataTime[0]).getTime(),
  296. endDay: new Date(this.dataTime[1]).getTime()
  297. }).then(res => {
  298. this.pdfData = res.data
  299. let windTowerInfo = this.pdfData.windTowerInfo.windTowerInfo
  300. /*基本信息*/
  301. this.windTowerInfo = {
  302. name: windTowerInfo.name,
  303. equipmentNo: windTowerInfo.equipmentNo,
  304. installationTime: windTowerInfo.installationTime,
  305. startTime: this.pdfData.windTowerInfo.startTime,
  306. endTime: this.pdfData.windTowerInfo.endTime,
  307. longitude: windTowerInfo.longitude,
  308. latitude: windTowerInfo.latitude,
  309. wsHeight: windTowerInfo.heights,
  310. wdHeight: windTowerInfo.wdHeights
  311. }
  312. /*完整性*/
  313. this.dataIntegrity= {
  314. time: windTowerInfo.installationTime,
  315. startTime: this.pdfData.windTowerInfo.startTime,
  316. integrityRate: this.pdfData.windTowerInfo.percentage,
  317. totalNum: this.pdfData.windTowerInfo.allCount
  318. }
  319. /*环境数据*/
  320. this.envTableData= this.pdfData.statisticsData.environment
  321. this.wsAndwd = {
  322. statisticsDataFen:this.pdfData.statisticsDataFen,
  323. statisticsWindTowerStatusDataFenMonth:this.pdfData.statisticsWindTowerStatusDataFenMonth,
  324. statisticsWindTowerStatusDataFenWpd:this.pdfData.statisticsWindTowerStatusDataFenWpd
  325. }
  326. this.roseData = this.pdfData.roseChart
  327. this.weibull = this.pdfData.weibull
  328. this.turbulenceData = this.pdfData.statisticsWindTowerStatusDataFenTur
  329. this.shearData = this.pdfData.statisticsWindTowerStatusDataShear
  330. this.loading = false
  331. this.downLoading = false
  332. }).catch(err => {
  333. this.loading = false
  334. this.downLoading = false
  335. })
  336. },
  337. changeCft() {
  338. let data = this.startDateAndEndDate.find(w => w.value == this.cftId)
  339. let time = this.defaultTimeData.find(w => w.eqId == this.cftId)
  340. console.log(time)
  341. this.dataTime = [time.startTime,time.endTime]
  342. this.changeHeight(data)
  343. },
  344. changeMonth(value) {
  345. // 今天是月初并且选择的月份是当月
  346. let endTime = new Date(value[1])
  347. let startTime = new Date(value[0])
  348. this.dataTime[0] = startTime.getTime()
  349. if (new Date().getDate() === 1 && endTime.getMonth() + 1 === new Date().getMonth() + 1) {
  350. this.dataTime[1] = endTime.getTime() - 1000 * 60 * 60 * 24
  351. } else {
  352. var data = new Date(value[1]);
  353. data.setMonth(data.getMonth() + 1);
  354. data.setDate(1);
  355. data.setHours(0);
  356. data.setSeconds(0);
  357. data.setMinutes(0);
  358. var timeEnd = (parseInt(data.getTime() / 1000) - 1) * 1000;
  359. this.dataTime[1] = timeEnd //最后一天23:59:59的时间戳
  360. }
  361. },
  362. async getPdf() {
  363. if(this.windTowerInfo.name !== undefined && this.windTowerInfo.name !== null){
  364. this.downLoading = true
  365. await htmlToPdf.downloadPDF(document.querySelector('#dataAnalysisPdf'), this.windTowerInfo.name + '测风设备数据分析报告')
  366. this.downPdfTimer = setInterval(() => {
  367. if (Cookies.get('pdfKey')) {
  368. this.downLoading = false
  369. clearInterval(this.downPdfTimer)
  370. Cookies.remove("pdfKey");
  371. }
  372. }, 500)
  373. }else {
  374. this.$message.warning('请先生成报告模板')
  375. }
  376. },
  377. /*切换测风塔时改变层高option*/
  378. changeHeight(data) {
  379. if (data.heights != null) {
  380. var option = []
  381. let str = data.heights.split(',')
  382. this.height = str[0]
  383. // this.height = null
  384. for (let i = 0; i < str.length; i++) {
  385. let filter = this.allOptions.find(w => w.value == str[i])
  386. option.push(filter)
  387. }
  388. this.options = option
  389. } else {
  390. this.height = "10"
  391. // this.height = null
  392. this.options = this.allOptions
  393. }
  394. },
  395. /*合并单元格*/
  396. arraySpanMethod({row, column, rowIndex, columnIndex}) {
  397. if (rowIndex === 0 || rowIndex === 1) {
  398. if (columnIndex === 0) {
  399. return [1, 2];
  400. } else if (columnIndex === 1) {
  401. return [0, 0];
  402. }
  403. }
  404. if (columnIndex === 0) {
  405. if (rowIndex % 2 === 0) {
  406. return {
  407. rowspan: 2,
  408. colspan: 1
  409. };
  410. } else {
  411. return {
  412. rowspan: 0,
  413. colspan: 0
  414. };
  415. }
  416. }
  417. },
  418. }
  419. }
  420. </script>
  421. <style scoped>
  422. .myCarousel {
  423. width: 600px;
  424. height: 30px;
  425. background-color: #ffba00;
  426. border-radius: 5px;
  427. color: #f8f8f8;
  428. display: flex;
  429. justify-content: center;
  430. align-items: center;
  431. }
  432. .condition {
  433. display: flex;
  434. margin: .5%;
  435. }
  436. .conditionOne, .conditionTwo, .seachBtu {
  437. display: inline-block;
  438. }
  439. .conditionTwo, .seachBtu {
  440. margin-left: .5%;
  441. }
  442. /deep/ .seachBtu .el-loading-spinner {
  443. font-size: 30px;
  444. }
  445. /deep/ .condition .el-button--mini {
  446. height: 32px;
  447. }
  448. #dataAnalysisPdf {
  449. width: 1661px;
  450. font-size: 20px;
  451. }
  452. #dataAnalysisPdf h1, #dataAnalysisPdf h2, #dataAnalysisPdf h3 {
  453. font-weight: bold;
  454. }
  455. .text {
  456. margin-left: 40px;
  457. font-size: 24px;
  458. }
  459. .pdfTableDiv {
  460. margin: 0 auto;
  461. display: flex;
  462. flex-direction: column;
  463. }
  464. .tableTitle {
  465. margin: 0 auto;
  466. }
  467. .tableTitle span {
  468. font-weight: bold;
  469. }
  470. .descriptionsDiv /deep/ .el-descriptions__body .el-descriptions__table .el-descriptions-item__cell {
  471. text-align: center;
  472. }
  473. .descriptionsDiv /deep/ .el-descriptions-item__label.is-bordered-label {
  474. font-size: 20px;
  475. font-weight: bold;
  476. color: #000000;
  477. background: #ffffff;
  478. }
  479. .descriptionsDiv /deep/ .el-descriptions .is-bordered .el-descriptions-item__cell {
  480. border: 2px solid #000000;
  481. }
  482. .descriptionsDiv /deep/ .el-descriptions--medium.is-bordered .el-descriptions-item__cell {
  483. padding: 8px;
  484. }
  485. .descriptionsDiv /deep/ .el-descriptions-item__content {
  486. font-size: 20px;
  487. font-weight: bold;
  488. color: #000;
  489. }
  490. .rowDiv {
  491. display: flex;
  492. justify-content: center;
  493. }
  494. .pdfTable {
  495. width: 100%;
  496. border: 1px solid;
  497. border-right: none;
  498. font-weight: bold;
  499. color: #000;
  500. font-size: 20px
  501. }
  502. .rowDiv /deep/ .el-row {
  503. text-align: center;
  504. font-size: 20px;
  505. font-weight: bold;
  506. color: #000;
  507. line-height: 50px;
  508. /*border: 1px solid #000;*/
  509. border-top: 1px solid #000;
  510. border-left: 1px solid #000;
  511. }
  512. .rowDiv .tableCol {
  513. border: 1px solid #000;
  514. height: 44px;
  515. border-top: none;
  516. border-left: none;
  517. }
  518. .rowDiv /deep/ .el-table--border .el-table__cell {
  519. border-right: 1px solid #000000;
  520. border-bottom: 1px solid #000;
  521. }
  522. .rowDiv /deep/ .el-table .el-table__header-wrapper th, .el-table .el-table__fixed-header-wrapper th {
  523. background-color: #ffffff;
  524. color: #000000;
  525. font-size: 20px;
  526. }
  527. </style>