index.vue 32 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045
  1. <template>
  2. <div class="app-container">
  3. <div class="dark-el-input dark-el-button">
  4. <el-form ref="queryForm" size="small" :inline="true" popper-class="cpp-popper">
  5. <el-form-item label="预测日期">
  6. <el-date-picker
  7. :clearable="false"
  8. v-model="dateTime"
  9. type="date"
  10. :picker-options="expireDateOption"
  11. placeholder="选择生成日期"
  12. popper-class="cpp-popper"
  13. >
  14. </el-date-picker>
  15. </el-form-item>
  16. <el-form-item label="场站名称">
  17. <el-select v-model="stationCode" placeholder="请选择" popper-class="cpp-popper">
  18. <el-option
  19. v-for="item in stationList"
  20. :key="item.value"
  21. :label="item.label"
  22. :value="item.value">
  23. </el-option>
  24. </el-select>
  25. </el-form-item>
  26. <el-form-item>
  27. <el-button type="primary" size="small" style="margin-left: 5px" icon="el-icon-search" @click="dataQuery">
  28. 查询
  29. </el-button>
  30. </el-form-item>
  31. </el-form>
  32. </div>
  33. <el-row>
  34. <el-col :span="9">
  35. <div class="divDescribe">调控策略</div>
  36. <div class="divDescribe">调控截止时间:{{ this.dqEndTime }}</div>
  37. <div class="divDescribe">调控方式:调控值=原始值*系数+数值</div>
  38. <div class="divDescribeBtn">
  39. <div class="dark-el-input dark-el-button">
  40. <el-button type="primary" size="small" style="margin-left: 5px" @click="quickUse">一键应用</el-button>
  41. <el-button type="primary" size="small" style="margin-left: 5px" @click="usualSet">设为常用</el-button>
  42. </div>
  43. </div>
  44. <div class="divTable">
  45. <el-table
  46. :data="tableData"
  47. :loading="loading"
  48. size="mini" height="60vh"
  49. style="width: 100%;">
  50. <el-table-column
  51. prop="time"
  52. header-align="center"
  53. align="center"
  54. label="时间" fixed min-width="50px"
  55. >
  56. </el-table-column>
  57. <el-table-column
  58. prop="xs"
  59. header-align="center"
  60. align="center"
  61. label="系数" min-width="50px">
  62. <template slot-scope="scope">
  63. <vxe-input type="number" v-model="scope.row.xs" size="small" style="width:100%" min="0"
  64. placeholder="" @change="setValueByManual(scope.row,scope.$index)"></vxe-input>
  65. </template>
  66. </el-table-column>
  67. <el-table-column
  68. prop="sz"
  69. header-align="center"
  70. align="center"
  71. label="数值" min-width="50px">
  72. <template slot-scope="scope">
  73. <vxe-input type="number" v-model="scope.row.sz" size="small" style="width:100%"
  74. placeholder="" @change="setValueByManual(scope.row,scope.$index)"></vxe-input>
  75. </template>
  76. </el-table-column>
  77. <el-table-column
  78. prop="ysValue"
  79. header-align="center"
  80. align="center"
  81. label="原始值" min-width="60px">
  82. </el-table-column>
  83. <el-table-column
  84. prop="tkValue"
  85. header-align="center"
  86. align="center"
  87. label="调控值"
  88. :max="capacity"
  89. :min="0" min-width="60px"
  90. >
  91. </el-table-column>
  92. </el-table>
  93. </div>
  94. <div class="tkBtn">
  95. <div class="dark-el-input dark-el-button">
  96. <el-button type="primary" size="small" style="margin-left: 5px" @click="tkDialog">调控功率</el-button>
  97. </div>
  98. </div>
  99. </el-col>
  100. <el-col :span="15">
  101. <div style="width: 100%;height: 82vh" id="tkcharts"></div>
  102. </el-col>
  103. </el-row>
  104. <div class="dark-el-dialog">
  105. <el-dialog :visible.sync="usualOpen" :before-close="cancelUsual" :close-on-click-modal="false" width="450px"
  106. height="600px">
  107. <el-form ref="usualForm" :model="usualForm" width="430px" label-width="70px">
  108. <el-row class="mb4">
  109. <el-col :span="24">
  110. <el-form-item label="常用名称" prop="name">
  111. <el-input style="width: 100%" v-model="usualForm.usualName" maxlength="15" popper-class="cpp-popper"/>
  112. </el-form-item>
  113. </el-col>
  114. </el-row>
  115. <el-row class="mb4">
  116. <el-col>
  117. <div style="color: #fff">保存常用名可以在一键应用中找到历史调控策略。</div>
  118. </el-col>
  119. </el-row>
  120. </el-form>
  121. <div slot="footer" class="dialog-footer">
  122. <el-button type="primary" @click="commitUsual">确 定</el-button>
  123. <el-button @click="cancelUsual">取 消</el-button>
  124. </div>
  125. </el-dialog>
  126. </div>
  127. <div class="dark-el-dialog">
  128. <el-dialog :visible.sync="tkOpen" :close-on-click-modal="false" width="700px" height="600px">
  129. <div class="flex" style="color:#ffffff;">
  130. 确认对
  131. <span style="background: #d3a4ff">{{ this.tkrq }}</span>
  132. 日,
  133. <span style="background: #d3a4ff">{{ this.stationName }}</span>
  134. 的短期功率调控,调控后数据将下发到对应场站上报调度。
  135. </div>
  136. <div slot="footer" class="dialog-footer">
  137. <el-button type="primary" @click="tkCommit">确 定</el-button>
  138. <el-button @click="tkCancel">取 消</el-button>
  139. </div>
  140. </el-dialog>
  141. </div>
  142. <!-- 策略选择弹窗 -->
  143. <div class="dark-el-dialog">
  144. <el-dialog :visible.sync="quickUseOpen" :before-close="cancelQuickUse" :close-on-click-modal="false"
  145. style="height: calc(100% - 50px)">
  146. <div class="reg-config-container flex justify-between">
  147. <div class="reg-config-con">
  148. <span class="flex justify-center dialog-text-title">策略选择</span>
  149. <!-- 策略列表 -->
  150. <div class="reg-config flex">
  151. <div class="reg-config-radio" style="margin-top: 15px">
  152. <el-radio v-model="vradio" label="1" @click.native.prevent="radioChange('1')">快捷选择历史策略:
  153. </el-radio>
  154. </div>
  155. <div class="flex-column reg-config-btu">
  156. <!-- 循环生成按钮 -->
  157. <el-button
  158. v-for="(button, index) in buttons"
  159. :key="index"
  160. @click="handleButtonClick(button.usualName)"
  161. >
  162. {{ button.usualName }}
  163. </el-button>
  164. </div>
  165. </div>
  166. <div class="reg-config flex items-center">
  167. <div class="reg-config-radio">
  168. <el-radio v-model="vradio" label="2" @click.native.prevent="radioChange('2')">选择历史策略:</el-radio>
  169. </div>
  170. <div>
  171. <el-select ref="selectUsualName" v-model="usualId" placeholder="请选择" popper-class="cpp-popper"
  172. :disabled="usualDisabled" @change="changeUsualName">
  173. <el-option
  174. v-for="item in usualList"
  175. :key="item.id"
  176. :label="item.usualName"
  177. :value="item.id">
  178. </el-option>
  179. </el-select>
  180. </div>
  181. </div>
  182. <div class="reg-config flex items-center" style="margin-top: 18px">
  183. <div class="reg-config-radio">
  184. <el-radio v-model="vradio" label="3" @click.native.prevent="radioChange('3')">选择中心侧模型:</el-radio>
  185. </div>
  186. <div>
  187. <el-select v-model="modelId" placeholder="请选择" popper-class="cpp-popper"
  188. :disabled="modelDisabled" @change="changeForecastModel">
  189. <el-option
  190. v-for="item in forecastModelList"
  191. :key="item.dictValue"
  192. :label="item.dictLabel"
  193. :value="item.dictValue">
  194. </el-option>
  195. </el-select>
  196. </div>
  197. </div>
  198. <div id="currentSelectFunction" style="display: none;margin-top: 30px;margin-left: 24px;"
  199. class="reg-config flex items-center">
  200. <div>当前选择策略:</div>
  201. <div style="width: 215px">
  202. {{ this.currentStrategy }}
  203. </div>
  204. <div>
  205. <el-button @click="trialPreview">预览</el-button>
  206. <el-button id="trialDeleteBtnId" @click="trialDelete" v-if="showDeleteButton">删除</el-button>
  207. </div>
  208. </div>
  209. <div slot="footer" class="reg-dialog-footer">
  210. <el-button type="primary" @click="quickUseCommit">一键应用</el-button>
  211. <el-button @click="cancelQuickUse">取 消</el-button>
  212. </div>
  213. </div>
  214. <!-- <el-divider direction="vertical" style="height: calc(100% - 30px)"></el-divider>-->
  215. <div>
  216. <!-- 预览表格 -->
  217. <span class="flex justify-center dialog-text-title">预览策略展示</span>
  218. <el-table
  219. :data="trialData"
  220. height="550px"
  221. :loading="loading"
  222. size="mini"
  223. style="width: 100%;margin-top: 13px;">
  224. <el-table-column
  225. prop="time"
  226. header-align="center"
  227. align="center"
  228. label="时间"
  229. >
  230. </el-table-column>
  231. <el-table-column
  232. prop="xs"
  233. header-align="center"
  234. align="center"
  235. label="系数">
  236. </el-table-column>
  237. <el-table-column
  238. prop="sz"
  239. header-align="center"
  240. align="center"
  241. label="数值">
  242. </el-table-column>
  243. <el-table-column
  244. prop="ysValue"
  245. header-align="center"
  246. align="center"
  247. label="原始值">
  248. </el-table-column>
  249. <el-table-column
  250. prop="tkValue"
  251. header-align="center"
  252. align="center"
  253. label="调控值"
  254. :max="capacity"
  255. :min="0"
  256. >
  257. </el-table-column>
  258. </el-table>
  259. </div>
  260. </div>
  261. </el-dialog>
  262. </div>
  263. </div>
  264. </template>
  265. <script>
  266. import * as echarts from "echarts";
  267. import {fontSize} from "../../../utils";
  268. export default {
  269. name: 'inverterinfo',
  270. data() {
  271. return {
  272. showDeleteButton:true,
  273. dqEndTime: '',
  274. markLineData: new Array(),
  275. visualMapPieces: new Array(),
  276. trialData: [],
  277. usualDisabled: true,
  278. modelDisabled: true,
  279. vradio: '1',
  280. buttons: new Array(),
  281. usualId: '',
  282. modelId: '',
  283. usualList: [],
  284. forecastModelList: [],
  285. currentStrategy: '',
  286. stationName: '',
  287. tkrq: '',
  288. quickUseOpen: false,
  289. tkOpen: false,
  290. usualOpen: false,
  291. usualForm: {
  292. usualName: undefined
  293. },
  294. expireDateOption: {
  295. disabledDate(time) {
  296. return (time.getTime() > Date.now() + 8.64e7 *10) || (time.getTime() < Date.now())
  297. }
  298. },
  299. loading: false,
  300. symbolSize: 8,
  301. capacity: '',
  302. tkData: [],
  303. tableData: [],
  304. hoursArray: [],
  305. chart: null,
  306. form: [],
  307. dateTime: new Date(new Date().toLocaleDateString()).getTime() + (60 * 60 * 24 * 1000),
  308. stationList: [],
  309. stationCode: '',
  310. ysData: [],
  311. refUpData: [],
  312. refDownData: [],
  313. chartOption: {
  314. backgroundColor: 'transparent',
  315. title: {
  316. top: 20,
  317. text: '短期调控曲线',
  318. textStyle: {
  319. fontWeight: 'normal',
  320. fontSize: fontSize(.16),
  321. },
  322. left: 'center'
  323. },
  324. tooltip: {
  325. trigger: 'axis',
  326. axisPointer: {
  327. lineStyle: {
  328. color: '#57617B'
  329. }
  330. }
  331. },
  332. legend: {
  333. top: 20,
  334. icon: 'rect',
  335. itemWidth: 14,
  336. itemHeight: 5,
  337. itemGap: 13,
  338. data: ['原始值', '调控值', '参考值上限', '参考值下限'],
  339. // right: '4%',
  340. right: 0,
  341. textStyle: {
  342. fontSize: fontSize(.14),
  343. // color: this.lineColor
  344. },
  345. selected: {
  346. '原始值': true,
  347. '调控值': true,
  348. '参考值上限': true,
  349. '参考值下限': true,
  350. }
  351. },
  352. dataZoom: [{
  353. type: 'inside'
  354. }],
  355. grid: {
  356. top: 100,
  357. left: '2%',
  358. right: '2%',
  359. bottom: '10%',
  360. containLabel: true
  361. },
  362. xAxis: [{
  363. type: 'category',
  364. boundaryGap: false,
  365. axisLine: {onZero: false},
  366. }],
  367. yAxis: [{
  368. type: 'value',
  369. name: 'MW',
  370. axisTick: {
  371. show: false
  372. },
  373. axisLabel: {
  374. margin: 10,
  375. textStyle: {
  376. fontSize: 14
  377. }
  378. },
  379. splitLine: {
  380. lineStyle: {
  381. color: '#57617B'
  382. }
  383. }
  384. }],
  385. series: [{
  386. name: '原始值',
  387. type: 'line',
  388. smooth: true,
  389. symbol: 'circle',
  390. symbolSize: 5,
  391. showSymbol: false,
  392. connectNulls: true,
  393. lineStyle: {
  394. normal: {
  395. width: 2
  396. }
  397. },
  398. itemStyle: {
  399. normal: {
  400. color: 'rgb(219,50,51)',
  401. borderWidth: 12
  402. }
  403. },
  404. data: this.ysData
  405. },
  406. {
  407. id: 'a',
  408. name: '调控值',
  409. type: 'line',
  410. showSymbol: false,
  411. smooth: true,
  412. symbol: 'circle',
  413. symbolSize: 10,
  414. connectNulls: true,
  415. lineStyle: {
  416. normal: {
  417. color: 'rgb(0,136,212)',
  418. width: 2
  419. }
  420. },
  421. itemStyle: {
  422. normal: {
  423. color: 'rgb(0,136,212)',
  424. borderWidth: 50
  425. }
  426. },
  427. data: []
  428. },
  429. {
  430. name: '参考值上限',
  431. type: 'line',
  432. smooth: true,
  433. symbol: 'circle',
  434. connectNulls: true,
  435. symbolSize: 5,
  436. showSymbol: false,
  437. lineStyle: {
  438. normal: {
  439. width: 2,
  440. type: 'dashed' //设置线条类型
  441. }
  442. },
  443. itemStyle: {
  444. normal: {
  445. color: '#00FF00',
  446. borderWidth: 12
  447. }
  448. },
  449. data: this.refUpData
  450. },
  451. {
  452. name: '参考值下限',
  453. type: 'line',
  454. smooth: true,
  455. symbol: 'circle',
  456. connectNulls: true,
  457. symbolSize: 5,
  458. showSymbol: false,
  459. lineStyle: {
  460. normal: {
  461. width: 2,
  462. type: 'dashed' //设置线条类型
  463. }
  464. },
  465. itemStyle: {
  466. normal: {
  467. color: 'rgb(167,27,189)',
  468. borderWidth: 12
  469. }
  470. },
  471. data: this.refDownData
  472. },
  473. ]
  474. }
  475. }
  476. },
  477. created() {
  478. this.getStationCode()
  479. },
  480. mounted() {
  481. this.initChart()
  482. },
  483. beforeDestroy() {
  484. if (!this.chart) {
  485. return
  486. }
  487. this.chart.dispose()
  488. this.chart = null
  489. },
  490. computed: {},
  491. methods: {
  492. // 中心侧预测模型选择
  493. changeForecastModel(dictValue){
  494. const item = this.forecastModelList.find(item => item.dictValue == dictValue)
  495. let dictLabel = item ? item.dictLabel : ''
  496. this.currentStrategy = dictLabel
  497. document.getElementById("currentSelectFunction").style.display = ''
  498. },
  499. // 策略名称下拉框选择
  500. changeUsualName(id) {
  501. const item = this.usualList.find(item => item.id == id)
  502. let usualName = item ? item.usualName : ''
  503. this.currentStrategy = usualName
  504. document.getElementById("currentSelectFunction").style.display = ''
  505. },
  506. radioChange(radioValue) {
  507. document.getElementById("currentSelectFunction").style.display = 'none'
  508. this.currentStrategy = ''
  509. this.trialData = []
  510. if (radioValue == '1') {
  511. // 显示删除按钮
  512. this.showDeleteButton = true
  513. this.vradio = '1'
  514. // 常用策略下拉框名称清空
  515. this.usualId = ''
  516. // 常用策略下拉框不可用
  517. this.usualDisabled = true
  518. // 中心模型下拉框名称清空
  519. this.modelId = ''
  520. // 中心模型下拉框不可用
  521. this.modelDisabled = true
  522. }
  523. else if (radioValue == '2') {
  524. // 显示删除按钮
  525. this.showDeleteButton = true
  526. this.vradio = '2'
  527. // 常用策略下拉框可用
  528. this.usualDisabled = false
  529. this.modelId = ''
  530. // 中心模型下拉框不可用
  531. this.modelDisabled = true
  532. }
  533. else if (radioValue == '3') {
  534. // 隐藏删除按钮
  535. this.showDeleteButton = false
  536. this.vradio = '3'
  537. this.usualId = ''
  538. // 常用策略下拉框不可用
  539. this.usualDisabled = true
  540. // 中心模型下拉框可用
  541. this.modelDisabled = false
  542. }
  543. },
  544. // 默认常用按钮事件
  545. handleButtonClick(usualName) {
  546. if (this.vradio == '1') {
  547. // 执行常用按钮点击
  548. this.currentStrategy = usualName
  549. document.getElementById("currentSelectFunction").style.display = ''
  550. }
  551. },
  552. async executeTrial() {
  553. const param = {
  554. "selectRadio": this.vradio,
  555. "usualName": this.currentStrategy,
  556. "stationCode": this.tableData[0].stationCode,
  557. "time": new Date(this.tableData[0].forecastDate).getTime()
  558. }
  559. // 获取策略名称的系数和数值
  560. await this.$axios.get('/dqRegulationController/trialData', {params: param}).then(response => {
  561. this.trialData = response.data
  562. })
  563. },
  564. // 删除按钮点击
  565. trialDelete() {
  566. if (this.currentStrategy == '') {
  567. this.$message.warning("请选择策略名称进行删除!")
  568. return
  569. }
  570. this.$confirm('是否确认删除【' + this.currentStrategy + '】?', '提示', {
  571. confirmButtonText: '确定',
  572. cancelButtonText: '取消',
  573. type: 'warning'
  574. }).then(() => {
  575. // 提交名称及系数配置
  576. const formData = new FormData()
  577. formData.append('usualName', this.currentStrategy)
  578. this.$axios.post('/dqUsualController/deleteUsual', formData, {
  579. headers: {
  580. 'Content-Type': 'multipart/form-data' // 设置请求头,确保服务器正确解析 FormData
  581. }
  582. }).then((res) => {
  583. this.$message.success('删除策略成功!')
  584. document.getElementById("currentSelectFunction").style.display = "none"
  585. this.trialData = []
  586. // 重新渲染下拉框
  587. this.renderUsual()
  588. }).catch((error) => {
  589. })
  590. })
  591. },
  592. // 预览按钮点击
  593. trialPreview() {
  594. if (this.currentStrategy == '') {
  595. this.$message.warning("请选择策略名称进行预览!")
  596. return
  597. }
  598. this.executeTrial()
  599. },
  600. // 一键应用中确定
  601. async quickUseCommit() {
  602. if (this.currentStrategy == '') {
  603. this.$message.warning("请选择策略进行应用!")
  604. return
  605. }
  606. await this.executeTrial()
  607. if (this.trialData.length==0){
  608. this.$message.warning("此策略无数据,不能一键应用!")
  609. return
  610. }
  611. else{
  612. // 将列表数据赋值给底层列表
  613. this.tableData = this.trialData
  614. // 将预算的调控曲线赋值给底层曲线上
  615. let tkArray = new Array()
  616. for (var i = 0; i < this.tableData.length; i++) {
  617. let array = new Array()
  618. array.push(this.tableData[i].time)
  619. array.push(this.tableData[i].tkValue)
  620. tkArray.push(array)
  621. }
  622. this.tkData = tkArray
  623. this.chartOption.series[1].data = this.tkData
  624. this.chart.setOption(this.chartOption)
  625. //再调用updatePosition
  626. this.updatePosition()
  627. this.cancelQuickUse()
  628. }
  629. },
  630. // 一键应用中取消按钮
  631. cancelQuickUse() {
  632. this.quickUseOpen = false;
  633. this.trialData = []
  634. this.currentStrategy = ''
  635. this.buttons = []
  636. this.vradio = '1'
  637. this.usualDisabled = true
  638. this.modelDisabled = true
  639. this.usualId=''
  640. this.modelId=''
  641. document.getElementById("currentSelectFunction").style.display = 'none'
  642. },
  643. renderUsual() {
  644. this.buttons = []
  645. this.usualId = ''
  646. this.currentStrategy = ''
  647. // 先获取常用下拉框
  648. this.$axios.get('/dqUsualController/getUsualList').then(response => {
  649. this.usualList = response.data.tempShortUsualList
  650. if (this.usualList.length > 0) {
  651. // 循环list,将前5个给默认常用,将第1个默认选中下拉框
  652. for (let i = 0; i < this.usualList.length; i++) {
  653. if (i < 5) {
  654. this.buttons.push(this.usualList[i])
  655. }
  656. }
  657. }
  658. this.forecastModelList = response.data.forecastModelList
  659. })
  660. },
  661. quickUse() {
  662. if (this.tableData.length == 0) {
  663. this.$message.warning("调控列表为空,不能操作!")
  664. return
  665. }
  666. this.renderUsual()
  667. this.quickUseOpen = true
  668. },
  669. // 点击设为常用按钮触发
  670. usualSet() {
  671. if (this.tableData.length == 0) {
  672. this.$message.warning("调控列表为空,不能操作!")
  673. return
  674. }
  675. this.usualOpen = true
  676. },
  677. // 设为常用弹出框保存按钮
  678. commitUsual() {
  679. if (this.tableData == undefined || this.tableData.length == 0) {
  680. this.$message.warning("请查询列表才可以设为常用!")
  681. return
  682. }
  683. if (this.usualForm.usualName == null || this.usualForm.usualName == '' || this.usualForm.usualName == undefined) {
  684. this.$message.warning("请输入常用名称!")
  685. return
  686. } else {
  687. let tempUsualName = this.usualForm.usualName.trim()
  688. if (tempUsualName == '') {
  689. this.$message.warning("请输入常用名称!")
  690. return
  691. }
  692. // 提交名称及系数配置
  693. const param = {
  694. "tempShortRegulationDtoList": this.tableData,
  695. "usualName": tempUsualName
  696. }
  697. this.$axios.post('/dqUsualController/saveUsual', param).then((res) => {
  698. this.$message.success('常用策略保存成功!')
  699. this.usualOpen = false
  700. this.resetUsual()
  701. }).catch((error) => {
  702. })
  703. }
  704. },
  705. // 表单重置
  706. resetUsual() {
  707. this.usualForm = {
  708. usualName: undefined,
  709. },
  710. this.resetForm("usualForm");
  711. },
  712. // 取消按钮
  713. cancelUsual() {
  714. this.usualOpen = false;
  715. this.resetUsual();
  716. },
  717. tkDialog() {
  718. // 判断截止时间,超出时间不允许调控
  719. const now = new Date();
  720. if (now.getTime() > new Date(this.dqEndTime)) {
  721. this.$message.warning("截止时间已过,不能进行调控!")
  722. return
  723. }
  724. if (this.tableData.length == 0) {
  725. this.$message.warning("调控列表为空,不能调控!")
  726. return
  727. }
  728. for (let i=0; i<this.tableData.length;i++){
  729. if (this.tableData[i].tkValue>this.capacity){
  730. this.$message.warning("列表中调控值存在超装机容量现象,不能调控!")
  731. return
  732. }
  733. }
  734. const date = new Date(this.dateTime); // 如果long是毫秒
  735. const year = date.getFullYear();
  736. const month = (date.getMonth() + 1).toString().padStart(2, '0');
  737. const day = date.getDate().toString().padStart(2, '0');
  738. this.tkrq = `${year}-${month}-${day}`; // 根据需要可以添加时间部分
  739. const item = this.stationList.find(item => item.value === this.stationCode)
  740. this.stationName = item ? item.label : ''
  741. this.tkOpen = true
  742. },
  743. tkCancel() {
  744. this.tkOpen = false
  745. },
  746. // 调控列表提交
  747. tkCommit() {
  748. if (this.tableData.length == 0) {
  749. this.$message.warning("调控列表为空,不能进行提交!")
  750. return
  751. }
  752. // 判断系数和数值2个字段是否有为空
  753. for (let i = 0; i < this.tableData.length; i++) {
  754. if (isNaN(this.tableData[i].tkValue)) {
  755. this.$message.warning(this.tableData[i].time + "存在空值,不能进行提交!")
  756. return
  757. }
  758. }
  759. // 保存调控值列表
  760. this.$axios.post('/dqRegulationController/updateDqRegulation', this.tableData).then((res) => {
  761. this.$message.success('调控功率保存成功!')
  762. // this.dataQuery()
  763. }).catch((error) => {
  764. })
  765. this.tkOpen = false
  766. },
  767. //通过表格内系数或固定值修改 生成曲线以及最终预测结果
  768. setValueByManual(row, index) {
  769. if (row.xs !== undefined && row.sz !== undefined) {
  770. // 计算调控值
  771. row.tkValue = parseFloat((parseFloat(row.ysValue) * parseFloat(row.xs) + parseFloat(row.sz)).toFixed(2))
  772. if (row.tkValue < 0) {
  773. row.tkValue = 0
  774. }
  775. if (row.tkValue > this.capacity) {
  776. row.tkValue = this.capacity
  777. }
  778. // 赋值给表格
  779. this.tableData[index] = row
  780. // 遍历tableData封装调控曲线数组
  781. let tkArray = new Array()
  782. for (var i = 0; i < this.tableData.length; i++) {
  783. let array = new Array()
  784. array.push(this.tableData[i].time)
  785. array.push(this.tableData[i].tkValue)
  786. tkArray.push(array)
  787. }
  788. this.tkData = tkArray
  789. this.chartOption.series[1].data = this.tkData
  790. this.chart.setOption(this.chartOption)
  791. //再调用updatePosition
  792. this.updatePosition()
  793. }
  794. },
  795. async dataQuery() {
  796. this.loading = true
  797. let queryParams = {
  798. "stationCode": this.stationCode,
  799. "time": Math.round(this.dateTime),
  800. }
  801. await this.$axios.get('/dqRegulationController/queryData', {params: queryParams}).then(response => {
  802. this.chart.clear()
  803. this.capacity = response.data.electricField.capacity
  804. this.tableData = response.data.tempShortRegulationList
  805. this.ysData = response.data.ysData
  806. this.refUpData = response.data.refUpData
  807. this.refDownData = response.data.refDownData
  808. this.tkData = response.data.tkDataList
  809. this.draData()
  810. this.loading = false
  811. }).catch(() => {
  812. this.tableData = []
  813. this.ysData = []
  814. this.refUpData = []
  815. this.refDownData = []
  816. this.tkData = []
  817. this.chart.clear()
  818. this.chartOption.series[0].data = this.ysData
  819. this.chartOption.series[1].data = this.tkData
  820. this.chartOption.series[2].data = this.refUpData
  821. this.chartOption.series[3].data = this.refDownData
  822. this.chart.setOption(this.chartOption)
  823. this.loading = false
  824. });
  825. this.getDqEndTime()
  826. },
  827. draData() {
  828. let this1 = this;
  829. this.chartOption.series[0].data = this.ysData
  830. this.chartOption.series[1].data = this.tkData
  831. this.chartOption.series[2].data = this.refUpData
  832. this.chartOption.series[3].data = this.refDownData
  833. let myChart = this.chart
  834. let cap = this.capacity
  835. setTimeout(function () {
  836. myChart.setOption({
  837. graphic: this1.tkData.map(function (item, dataIndex) {
  838. return {
  839. type: 'circle',
  840. position: myChart.convertToPixel('grid', item),
  841. shape: {
  842. cx: 0,
  843. cy: 0,
  844. r: 10
  845. },
  846. invisible: true,
  847. draggable: true,
  848. ondrag: function (dx, dy,) {
  849. this1.onPointDragging(dataIndex, [item[0], dx.offsetY], cap);
  850. },
  851. onmousemove: function () {
  852. this1.showTooltip(dataIndex);
  853. },
  854. onmouseout: function () {
  855. this1.hideTooltip(dataIndex);
  856. },
  857. z: 100
  858. };
  859. })
  860. });
  861. }, 0);
  862. // window.addEventListener('resize', this1.updatePosition);
  863. myChart.on('dataZoom', this1.updatePosition);
  864. // 拖动曲线后,将数值重新赋值给表格
  865. this.chartOption.yAxis[0].max = this.capacity
  866. myChart.setOption(this.chartOption)
  867. },
  868. updatePosition() {
  869. let this1 = this;
  870. let myChart = this.chart
  871. myChart.setOption({
  872. graphic: this1.tkData.map(function (item, dataIndex) {
  873. return {
  874. position: myChart.convertToPixel('grid', item)
  875. };
  876. })
  877. });
  878. },
  879. showTooltip(dataIndex) {
  880. let myChart = this.chart
  881. myChart.dispatchAction({
  882. type: 'showTip',
  883. seriesIndex: 0,
  884. dataIndex: dataIndex
  885. });
  886. },
  887. hideTooltip(dataIndex) {
  888. let myChart = this.chart
  889. myChart.dispatchAction({
  890. type: 'hideTip'
  891. });
  892. },
  893. onPointDragging(dataIndex, pos, capacity) {
  894. let this1 = this;
  895. let myChart = this.chart
  896. this1.tkData[dataIndex][1] = myChart.convertFromPixel('grid', pos)[1].toFixed(2);
  897. if (myChart.convertFromPixel('grid', pos)[1].toFixed(2) > capacity) {
  898. this1.tkData[dataIndex][1] = capacity
  899. }
  900. if (myChart.convertFromPixel('grid', pos)[1].toFixed(2) < 0) {
  901. this1.tkData[dataIndex][1] = 0
  902. }
  903. // 赋值调控值字段
  904. this1.tableData[dataIndex].tkValue = this1.tkData[dataIndex][1]
  905. // 根据调控值更新表格中数值字段,数值=调控值-(原始值*系数)
  906. this1.tableData[dataIndex].sz = (this1.tkData[dataIndex][1] - (this1.tableData[dataIndex].ysValue * this1.tableData[dataIndex].xs)).toFixed(2)
  907. myChart.setOption(this.chartOption)
  908. // Update data
  909. myChart.setOption({
  910. series: [
  911. {
  912. id: 'a',
  913. data: this1.tkData,
  914. }
  915. ]
  916. });
  917. this.updatePosition()
  918. },
  919. // 获取短期截止时间
  920. async getDqEndTime() {
  921. await this.$axios({url: '/dqRegulationController/getDqEndTime', method: 'get'}).then(response => {
  922. this.dqEndTime = response.data
  923. })
  924. },
  925. getStationCode() {
  926. this.$axios({url: '/electricfield/all', method: 'get'}).then(response => {
  927. this.stationList = response.data
  928. if (this.stationList.length > 0) {
  929. this.stationCode = this.stationList[0].value
  930. this.dataQuery()
  931. }
  932. })
  933. },
  934. initChart() {
  935. for (let i = 0; i < 24 * 60; i += 15) {
  936. let hours = Math.floor(i / 60);
  937. let minutes = i % 60;
  938. this.hoursArray.push(`${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}`);
  939. }
  940. this.chartOption.xAxis[0].data = this.hoursArray
  941. this.chart = echarts.init(document.getElementById('tkcharts'), 'dark')
  942. this.chart.setOption(this.chartOption)
  943. },
  944. }
  945. }
  946. </script>
  947. <style scoped>
  948. .divDescribe {
  949. position: relative;
  950. top: 20px; /* 向下移动15px */
  951. width: 100%;
  952. text-align: center
  953. }
  954. .divDescribeBtn {
  955. position: relative;
  956. top: 25px; /* 向下移动15px */
  957. width: 100%;
  958. text-align: right
  959. }
  960. .divTable {
  961. position: relative;
  962. top: 30px; /* 向下移动15px */
  963. width: 100%;
  964. text-align: center
  965. }
  966. .tkBtn {
  967. position: relative;
  968. top: 50px; /* 向下移动15px */
  969. width: 100%;
  970. text-align: center
  971. }
  972. .dialog-text-title {
  973. font-size: 16px;
  974. font-weight: bold;
  975. }
  976. .reg-config-container {
  977. height: 100%;
  978. }
  979. .reg-config-con {
  980. width: 50%;
  981. position: relative;
  982. }
  983. .reg-config {
  984. margin-top: 5px;
  985. }
  986. .reg-config-radio {
  987. width: 150px;
  988. }
  989. .reg-config-btu {
  990. width: 215px;
  991. //height: 190px; margin-top: 5px;
  992. }
  993. .reg-dialog-footer {
  994. position: absolute;
  995. bottom: 0;
  996. left: 35%;
  997. //text-align: center;
  998. }
  999. /deep/ .reg-config-btu .el-button:first-child {
  1000. margin-top: 5px;
  1001. }
  1002. /deep/ .reg-config-btu .el-button {
  1003. margin-top: 10px;
  1004. }
  1005. /deep/ .reg-config-btu .el-button:last-child {
  1006. margin-bottom: 10px;
  1007. }
  1008. /deep/ .reg-config-btu .el-button + .el-button {
  1009. margin-left: 0px;
  1010. }
  1011. </style>