储能智慧云平台web端
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

index.vue 29KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901
  1. <template>
  2. <div>
  3. <div class="title">
  4. <el-select
  5. v-model="Singlevalue"
  6. collapse-tags
  7. placeholder="选择电站"
  8. popper-class="custom-header"
  9. :max-collapse-tags="1"
  10. class="Space_content"
  11. size="large"
  12. @change="postemsDevice"
  13. >
  14. <el-option v-for="(item, index) in cities" :key="index" :label="item.stationName" :value="item.id" />
  15. <template #prefix>
  16. {{ (cities.find(s => s.id === Singlevalue) || {}).stationName }}
  17. </template>
  18. </el-select>
  19. <div class="title_"></div>
  20. <el-select
  21. v-model="emsDeviceId"
  22. collapse-tags
  23. placeholder="选择编号"
  24. popper-class="custom-header"
  25. :max-collapse-tags="1"
  26. class="Space_content"
  27. size="large"
  28. @change="getstationrealtime"
  29. >
  30. <template #prefix>
  31. {{ (emsDevice.find(s => s.id === emsDeviceId) || {}).id }}
  32. </template>
  33. <el-option v-for="item in emsDevice" :key="item.id" :label="item.emsDeviceId" :value="item.id" />
  34. </el-select>
  35. <div class="Equipmentright">
  36. <div></div>
  37. <div class="Equipmenttpye" v-if="realtime.onlineStatus == 1">
  38. <div class="equipmentborder"></div>
  39. 在线
  40. </div>
  41. <div class="Equipmenttpyes" v-else>
  42. <div class="equipmentborderif"></div>
  43. 离线
  44. </div>
  45. </div>
  46. </div>
  47. <div class="realtime">
  48. <el-row :gutter="20">
  49. <el-col :span="18">
  50. <el-card>
  51. <template #header>
  52. <div class="card-header">
  53. <span>实时数据</span>
  54. </div>
  55. </template>
  56. <div class="real_time">
  57. <div class="real_timediv">
  58. <el-card>
  59. <div class="real_timename">今日充电量</div>
  60. <div class="real_timeunit">{{ realtime.dayImportKwh }}<span class="real_timeunitcss"> kWh</span></div>
  61. </el-card>
  62. </div>
  63. <div class="real_timediv">
  64. <el-card>
  65. <div class="real_timename">今日放电量</div>
  66. <div class="real_timeunit">{{ realtime.dayExportKwh }} <span class="real_timeunitcss">kWh</span></div>
  67. </el-card>
  68. </div>
  69. <div class="real_timediv">
  70. <el-card>
  71. <div class="real_timename">累计充电量</div>
  72. <div class="real_timeunit">{{ realtime.accumulativeImportKwh }} <span class="real_timeunitcss">kWh</span></div>
  73. </el-card>
  74. </div>
  75. <div class="real_timediv">
  76. <el-card>
  77. <div class="real_timename">累计放电量</div>
  78. <div class="real_timeunit">{{ realtime.accumulativeExportKwh }} <span class="real_timeunitcss">kWh</span></div>
  79. </el-card>
  80. </div>
  81. <div class="real_timediv">
  82. <el-card>
  83. <div class="real_timename">电池堆SOC</div>
  84. <div class="real_timeunit">{{ realtime.soc }} <span class="real_timeunitcss">%</span></div>
  85. </el-card>
  86. </div>
  87. </div>
  88. <div class="trend">
  89. <div class="trend_left">
  90. <div class="trend_leftname">运行状态</div>
  91. <div class="trend_leftline">
  92. <img class="trend_imgdw" src="../../assets/images/dw.36d3b54f.png" alt="" />
  93. <div class="trend_line1">
  94. <div class="trend_linec"></div>
  95. </div>
  96. <div class="trend_Dots"></div>
  97. <div class="trend_line1">
  98. <div class="trend_line2"></div>
  99. </div>
  100. <img class="trend_household" src="../../assets/images/household.png" alt="" />
  101. </div>
  102. <div class="trend_between">
  103. <div class="trend_middle">
  104. <div class="trend_middley"></div>
  105. </div>
  106. <img class="trend_electricbox" src="../../assets/images/Electricbox.png" alt="" />
  107. </div>
  108. </div>
  109. <div class="trend_right">
  110. <div>功率趋势</div>
  111. <div>最大充电功率:107.00kW最大放电功率:80.20 kW 最大负载功率:- kW</div>
  112. <div class="trend_chart" ref="trendchart"></div>
  113. </div>
  114. </div>
  115. </el-card>
  116. </el-col>
  117. <el-col :span="6">
  118. <el-card>
  119. <template #header>
  120. <div class="card-header">
  121. <span>告警状态</span>
  122. </div>
  123. </template>
  124. <div class="Boxdiv">
  125. <div class="Boxdiv_">
  126. <div class="Boxdiv_left">
  127. <div class="Boxdiv_bottom">名称</div>
  128. </div>
  129. <div class="Boxdiv_right">
  130. <div class="Boxdiv_bottom">状态</div>
  131. </div>
  132. </div>
  133. <div class="Boxdiv_" v-for="(item, index) in device" :key="index">
  134. <div class="Boxdiv_left">
  135. <div class="Boxdiv_bottom">{{ item.deviceName }}</div>
  136. </div>
  137. <div class="Boxdiv_right">
  138. <div class="Boxdiv_bottom">
  139. <div v-if="item.emsCommStatus == 0" class="equipment">
  140. <!-- <div class="equipmentborderif"></div> -->
  141. 停机
  142. </div>
  143. <div v-else class="equipment">
  144. <!-- <div class="equipmentborder"></div> -->
  145. 运行
  146. </div>
  147. </div>
  148. </div>
  149. </div>
  150. </div>
  151. </el-card>
  152. </el-col>
  153. </el-row>
  154. </div>
  155. <!--
  156. -->
  157. <div class="realoperation">
  158. <el-card>
  159. <template #header>
  160. <div class="card-header">
  161. <div>实时运行</div>
  162. <div class="grid_divright">
  163. <div :class="timetype == 1 ? 'grid_divright_1' : 'grid_divright_2'" @click="recently(1)">实时</div>
  164. <div :class="timetype == 7 ? 'grid_divright_1' : 'grid_divright_2'" @click="recently(7)">近7日</div>
  165. <div :class="timetype == 31 ? 'grid_divright_1' : 'grid_divright_2'" @click="recently(31)">近31月</div>
  166. <el-date-picker
  167. v-model="value2"
  168. type="datetimerange"
  169. start-placeholder="开始时间"
  170. end-placeholder="结束时间"
  171. :default-value="value2"
  172. :disabled-date="pickerOptions"
  173. @change="datepicker"
  174. />
  175. </div>
  176. </div>
  177. </template>
  178. <div class="realoperationdiv">
  179. <div class="realoperationdiv1">数据类型</div>
  180. <div class="realoperationdiv2">
  181. <div class="realopscreen1">
  182. <div class="realopscreen1_top">
  183. <el-checkbox v-model="PCS" style="font-weight: 600" label="pcs:" size="large" color="#0052d9" /><el-select
  184. v-model="PCSvalue"
  185. placeholder="请选择pcs"
  186. size="large"
  187. style="width: 360px"
  188. >
  189. <el-option v-for="item in devicePCS" :key="item.deviceId" :label="item.deviceName" :value="item.deviceId" />
  190. </el-select>
  191. </div>
  192. <div class="realopscreen1_bottom">
  193. <el-checkbox v-model="PCS" style="font-weight: 600" label="有功功率" size="large" />
  194. </div>
  195. </div>
  196. <div class="realopscreen1">
  197. <div class="realopscreen1_top">
  198. <el-checkbox v-model="metertype" style="font-weight: 600" label="电表:" size="large" /><el-select
  199. v-model="metervalue"
  200. placeholder="请选择电表"
  201. size="large"
  202. style="width: 360px"
  203. >
  204. <el-option v-for="item in electricMeter" :key="item.deviceId" :label="item.deviceName" :value="item.deviceId" />
  205. </el-select>
  206. </div>
  207. <div class="realopscreen1_bottom">
  208. <el-checkbox v-model="metertype" style="font-weight: 600" label="有功功率" size="large" />
  209. </div>
  210. </div>
  211. <div class="realopscreen1">
  212. <div class="realopscreen1_top">
  213. <el-checkbox v-model="Battery" style="font-weight: 600" label="电池堆:" size="large" /><el-select
  214. v-model="Batteryvalue"
  215. placeholder="请选择电池堆"
  216. size="large"
  217. style="width: 360px"
  218. >
  219. <el-option
  220. v-for="item in batteryCluster"
  221. :key="item.deviceId"
  222. :label="item.deviceName"
  223. :value="item.deviceId"
  224. />
  225. </el-select>
  226. </div>
  227. <div class="realopscreen1_bottom">
  228. <el-checkbox v-model="socvalue" style="font-weight: 600" label="soc" size="large" />
  229. <el-checkbox v-model="maxvoltage" style="font-weight: 600" label="单体最高电压" size="large" />
  230. <el-checkbox v-model="minvoltage" style="font-weight: 600" label="单体最低电压" size="large" />
  231. </div>
  232. </div>
  233. </div>
  234. <el-button type="primary" size="large" color="#0052d9" @click="getpoststationdevice">查询</el-button>
  235. </div>
  236. <div class="gcurve_title">
  237. <div class="gcurve_tip"></div>
  238. <div>尖</div>
  239. <div class="gcurve_peak"></div>
  240. <div>峰</div>
  241. <div class="gcurve_flat"></div>
  242. <div>平</div>
  243. <div class="gcurve_valley"></div>
  244. <div>谷</div>
  245. </div>
  246. <div class="gcurve_chart" ref="operatingcurve"></div>
  247. </el-card>
  248. </div>
  249. <div class="income">
  250. <el-card>
  251. <template #header>
  252. <div class="card-header">
  253. <div>实时电量收益</div>
  254. </div>
  255. </template>
  256. <div>
  257. 日期:
  258. <el-date-picker
  259. v-model="pickervalue"
  260. type="date"
  261. placeholder="选择时间"
  262. size="large"
  263. clearable
  264. :disabled-date="pickerOptions"
  265. @change="pickerincome"
  266. />&ensp;&ensp;
  267. <el-button type="primary" size="large" color="#0052d9" @click="gatrevenue">查询</el-button>
  268. <el-button size="large" @click="onreset">重置</el-button>
  269. </div>
  270. <div class="income_div">
  271. <div class="income_title">
  272. <div class="income_title1">时间</div>
  273. <div class="income_title2">
  274. <div class="income_title2_">充电量(kWh)</div>
  275. <div class="income_title2_1">
  276. <div class="income_title2_11">尖</div>
  277. <div class="income_title2_11">峰</div>
  278. <div class="income_title2_11">平</div>
  279. <div class="income_title2_11">谷</div>
  280. <div class="income_title2_11">总</div>
  281. </div>
  282. </div>
  283. <div class="income_title3">
  284. <div class="income_title2_">放电量(kWh)</div>
  285. <div class="income_title2_1">
  286. <div class="income_title2_11">尖</div>
  287. <div class="income_title2_11">峰</div>
  288. <div class="income_title2_11">平</div>
  289. <div class="income_title2_11">谷</div>
  290. <div class="income_title2_11">总</div>
  291. </div>
  292. </div>
  293. <div class="income_title4">当前收益(元)</div>
  294. </div>
  295. <div class="income_ul" v-for="(item, index) in incomedata.list" :key="index">
  296. <div class="income_ul_left">{{ item.ymdHour }}</div>
  297. <div class="income_li1">
  298. <div class="income_title2_1">
  299. <div class="income_title2_11">{{ item.chargeSharpKwh.toFixed(2) }}</div>
  300. <div class="income_title2_11">{{ item.chargePeakKwh.toFixed(2) }}</div>
  301. <div class="income_title2_11">{{ item.chargeShoulderKwh.toFixed(2) }}</div>
  302. <div class="income_title2_11">{{ item.chargeValleyKwh.toFixed(2) }}</div>
  303. <div class="income_title2_11">{{ item.chargeKwh.toFixed(2) }}</div>
  304. </div>
  305. </div>
  306. <div class="income_li2">
  307. <div class="income_title2_1">
  308. <div class="income_title2_11">{{ item.dischargeSharpKwh.toFixed(2) }}</div>
  309. <div class="income_title2_11">{{ item.dischargePeakKwh.toFixed(2) }}</div>
  310. <div class="income_title2_11">{{ item.dischargeShoulderKwh.toFixed(2) }}</div>
  311. <div class="income_title2_11">{{ item.dischargeValleyKwh.toFixed(2) }}</div>
  312. <div class="income_title2_11">{{ item.dischargeKwh.toFixed(2) }}</div>
  313. </div>
  314. </div>
  315. <div class="income_ul_right">{{ item.profit.toFixed(2) }}</div>
  316. </div>
  317. <div class="income_ul">
  318. <div class="income_ul_left">总计</div>
  319. <div class="income_li1">
  320. <div class="income_title2_1">
  321. <div class="income_title2_11">{{ incomedata.total.chargeSharpKwh.toFixed(2) }}</div>
  322. <div class="income_title2_11">{{ incomedata.total.chargePeakKwh.toFixed(2) }}</div>
  323. <div class="income_title2_11">{{ incomedata.total.chargeShoulderKwh.toFixed(2) }}</div>
  324. <div class="income_title2_11">{{ incomedata.total.chargeValleyKwh.toFixed(2) }}</div>
  325. <div class="income_title2_11">{{ incomedata.total.chargeKwh.toFixed(2) }}</div>
  326. </div>
  327. </div>
  328. <div class="income_li2">
  329. <div class="income_title2_1">
  330. <div class="income_title2_11">{{ incomedata.total.dischargeSharpKwh.toFixed(2) }}</div>
  331. <div class="income_title2_11">{{ incomedata.total.dischargePeakKwh.toFixed(2) }}</div>
  332. <div class="income_title2_11">{{ incomedata.total.dischargeShoulderKwh.toFixed(2) }}</div>
  333. <div class="income_title2_11">{{ incomedata.total.dischargeValleyKwh.toFixed(2) }}</div>
  334. <div class="income_title2_11">{{ incomedata.total.dischargeKwh.toFixed(2) }}</div>
  335. </div>
  336. </div>
  337. <div class="income_ul_right">{{ incomedata.total.profit.toFixed(2) }}</div>
  338. </div>
  339. </div>
  340. </el-card>
  341. </div>
  342. </div>
  343. </template>
  344. <!-- -->
  345. <script setup lang="ts">
  346. import { onMounted, onUnmounted, Ref, ref } from "vue";
  347. import {
  348. stationstationName,
  349. postemsSystemsingleStation,
  350. poststationrealtime,
  351. poststationsystem,
  352. poststationdevice,
  353. postelectricityrevenue,
  354. poststationlist,
  355. stationrecord,
  356. stationcolor
  357. } from "@/api/home/Multisite";
  358. import * as echarts from "echarts";
  359. import { Station } from "@/api/interface";
  360. const intervalID = ref();
  361. const Singlevalue = ref("");
  362. const cities: Ref<Station.todo[]> = ref([]);
  363. const emsDevice: Ref<any[]> = ref([]);
  364. const emsDeviceId = ref("");
  365. const poststationstationName = async () => {
  366. const { data } = await stationstationName({});
  367. if (data.length == 0) {
  368. Singlevalue.value = "";
  369. return;
  370. } else {
  371. Singlevalue.value = data[0].id;
  372. }
  373. cities.value = data;
  374. postemsDevice();
  375. };
  376. const postemsDevice = async () => {
  377. emsDevice.value = [];
  378. const { data } = await postemsSystemsingleStation({}, Singlevalue.value);
  379. if (data.length == 0) {
  380. emsDeviceId.value = "";
  381. clearInterval(intervalID.value);
  382. return;
  383. } else {
  384. emsDeviceId.value = data[0].id;
  385. }
  386. emsDevice.value = data;
  387. // 清除定时器的示例
  388. clearInterval(intervalID.value);
  389. getstationrealtime();
  390. intervalID.value = setInterval(function () {
  391. getstationrealtime();
  392. }, 10000);
  393. };
  394. const realtime: Ref<Station.realtimeinfo> = ref({
  395. accumulativeExportKwh: 0,
  396. accumulativeImportKwh: 0,
  397. dayExportKwh: 0,
  398. dayImportKwh: 0,
  399. lastDataTime: "",
  400. onlineStatus: 0,
  401. soc: 0
  402. });
  403. const getstationrealtime = async () => {
  404. const { data } = await poststationrealtime({}, Singlevalue.value, emsDeviceId.value);
  405. realtime.value = data;
  406. await getpoststationdevice();
  407. await getstationsystem();
  408. await getstationdevice();
  409. await gatrevenue();
  410. };
  411. // 功率趋势图
  412. const trendchart = ref();
  413. const getstationsystem = async () => {
  414. const { data } = await poststationsystem({}, Singlevalue.value, emsDeviceId.value);
  415. powertrend(data.gridPower, data.storedPower);
  416. };
  417. const powertrend = (chartDataList: any[], storedPower: any[]) => {
  418. const dateList = chartDataList.map(function (item) {
  419. return item.ts.slice(-8);
  420. });
  421. const valueList = chartDataList.map(function (item) {
  422. return item.totalActivePower;
  423. });
  424. const secondList = storedPower.map(function (item) {
  425. return item.totalActivePower;
  426. });
  427. const trendchartvalue = echarts.init(trendchart.value);
  428. window.addEventListener(
  429. "resize",
  430. () => {
  431. trendchartvalue.resize();
  432. },
  433. false
  434. );
  435. let option = {
  436. grid: {
  437. left: "2%",
  438. right: "4%",
  439. bottom: "6%",
  440. containLabel: true
  441. },
  442. title: [
  443. {
  444. subtext: "有功功率/kW"
  445. }
  446. ],
  447. tooltip: {
  448. trigger: "axis"
  449. },
  450. xAxis: {
  451. data: dateList,
  452. type: "category",
  453. axisTick: {
  454. show: false // 这里设置为false隐藏X轴刻度线
  455. }
  456. },
  457. yAxis: {
  458. type: "value"
  459. },
  460. series: [
  461. {
  462. type: "line",
  463. showSymbol: false,
  464. data: valueList,
  465. lineStyle: {
  466. color: "#0691D9" // 设置折线颜色为红色
  467. }
  468. },
  469. {
  470. type: "line",
  471. stack: "Total",
  472. showSymbol: false,
  473. data: secondList
  474. }
  475. ]
  476. };
  477. console.log(valueList.length);
  478. console.log(secondList.length);
  479. if (valueList.length === 0 && secondList.length === 0) {
  480. trendchartvalue.setOption(
  481. {
  482. title: {
  483. text: "暂无数据",
  484. left: "center",
  485. top: "center",
  486. textStyle: {
  487. fontSize: 20,
  488. color: "#999"
  489. }
  490. },
  491. tooltip: {
  492. trigger: "item",
  493. formatter: "暂无数据"
  494. },
  495. legend: {
  496. // 清空图例
  497. data: [] // 清空图例内容
  498. },
  499. series: [] // 清空系列
  500. },
  501. true
  502. );
  503. } else {
  504. trendchartvalue.setOption(option, true);
  505. }
  506. // trendchartvalue.setOption(option, true);
  507. };
  508. const device: Ref<Station.systemdevice[]> = ref([]);
  509. const getstationdevice = async () => {
  510. const { data } = await poststationdevice({}, Singlevalue.value, emsDeviceId.value);
  511. device.value = data;
  512. };
  513. // 实时运行
  514. const timetype = ref(1);
  515. const value2 = ref();
  516. const pickerOptions = (time: { getTime: (arg0: Date) => number }) => {
  517. return time.getTime(new Date()) > Date.now();
  518. };
  519. // 选择实时运行
  520. const recently = (val: any) => {
  521. // 获取当前日期
  522. timetype.value = val;
  523. const today = new Date();
  524. const currentDate = today.toISOString().split("T")[0];
  525. const currentHour = today.getHours();
  526. const currentMinute = today.getMinutes();
  527. // 格式化小时、分钟和秒,确保它们始终有两位数
  528. const formattedHour = currentHour < 10 ? "0" + currentHour : currentHour;
  529. const formattedMinute = currentMinute < 10 ? "0" + currentMinute : currentMinute;
  530. // 拼接成 HH:MM:SS 的格式
  531. const currentTime = `${formattedHour}:${formattedMinute}`;
  532. // 获取过去 7 天的日期
  533. const sevenDaysAgoDate = new Date(today);
  534. sevenDaysAgoDate.setDate(today.getDate() - 7);
  535. const sevenDaysAgo = sevenDaysAgoDate.toISOString().split("T")[0];
  536. // 获取过去 31 天的日期
  537. const thirtyOneDaysAgoDate = new Date(today);
  538. thirtyOneDaysAgoDate.setDate(today.getDate() - 31);
  539. const thirtyOneDaysAgo = thirtyOneDaysAgoDate.toISOString().split("T")[0];
  540. if (val == 1) {
  541. value2.value = [currentDate + " " + "00:00", currentDate + " " + currentTime];
  542. } else if (val == 7) {
  543. value2.value = [sevenDaysAgo + " " + "00:00", currentDate + " " + currentTime];
  544. } else if (val == 31) {
  545. value2.value = [thirtyOneDaysAgo + " " + "00:00", currentDate + " " + currentTime];
  546. }
  547. getpoststationdevice();
  548. };
  549. const datepicker = (val: any) => {
  550. timetype.value = 0;
  551. value2.value = [formatDate(val[0]), formatDate(val[1])];
  552. getpoststationdevice();
  553. };
  554. const formatDate = (dateString: string | number | Date) => {
  555. const date = new Date(dateString);
  556. // 提取年、月、日、时、分信息
  557. const year = date.getFullYear();
  558. const month = String(date.getMonth() + 1).padStart(2, "0"); // 月份从0开始,需要加1,并确保是两位数
  559. const day = String(date.getDate()).padStart(2, "0"); // 确保是两位数
  560. const hours = String(date.getHours()).padStart(2, "0"); // 确保是两位数
  561. const minutes = String(date.getMinutes()).padStart(2, "0"); // 确保是两位数
  562. // 拼接成 "YYYY-MM-DD HH:MM" 格式
  563. const formattedDate = `${year}-${month}-${day} ${hours}:${minutes}`;
  564. return formattedDate;
  565. };
  566. // 实时运行筛选
  567. const PCS = ref(true);
  568. const PCSvalue = ref();
  569. // const power = ref(true);
  570. const metertype = ref(true);
  571. const metervalue = ref();
  572. // const powers = ref(true);
  573. const Battery = ref(true);
  574. const Batteryvalue = ref();
  575. const socvalue = ref(true);
  576. const maxvoltage = ref(true);
  577. const minvoltage = ref(true);
  578. const operatingcurve = ref();
  579. const devicePCS = ref();
  580. const electricMeter = ref();
  581. const batteryCluster = ref();
  582. // const batteryStack = ref([]);
  583. // poststationlist
  584. const getpoststationdevice = async () => {
  585. const { data } = await poststationlist({}, Singlevalue.value, emsDeviceId.value);
  586. PCSvalue.value = data.pcs[0].deviceId;
  587. metervalue.value = data.electricMeter[0].deviceId;
  588. Batteryvalue.value = data.batteryCluster[0].deviceId;
  589. devicePCS.value = data.pcs;
  590. electricMeter.value = data.electricMeter;
  591. batteryCluster.value = data.batteryCluster;
  592. let pcsdata = {};
  593. let Cluster = {};
  594. let Meter = {};
  595. let gridmeter = {};
  596. let stationcolorlist = [];
  597. if (PCS.value) {
  598. for (let index = 0; index < data.pcs.length; index++) {
  599. pcsdata = await getstationrecord(data.pcs[index].deviceId, "totalAcActivePower");
  600. }
  601. }
  602. if (Battery.value) {
  603. // for (let a = 0; a < data.batteryCluster.length; a++) {
  604. // let text = "";
  605. // if (socvalue.value) {
  606. // text = "soc";
  607. // } else if (maxvoltage.value) {
  608. // text = "maxCellVoltage";
  609. // } else if (minvoltage.value) {
  610. // text = "minCellVoltage";
  611. // } else if (socvalue.value && minvoltage.value && minvoltage.value) {
  612. // text = "soc,maxCellVoltage,minCellVoltage";
  613. // }
  614. Cluster = await getstationrecord(data.batteryCluster[0].deviceId, "soc");
  615. Cluster = await getstationrecord(data.batteryCluster[0].deviceId, "maxCellVoltage");
  616. Cluster = await getstationrecord(data.batteryCluster[0].deviceId, "minCellVoltage");
  617. Cluster = await getstationrecord(data.batteryCluster[0].deviceId, "soc,maxCellVoltage,minCellVoltage");
  618. // }
  619. }
  620. if (metertype.value) {
  621. for (let i = 0; i < data.electricMeter.length; i++) {
  622. if (i == 0) {
  623. Meter = await getstationrecord(data.electricMeter[i].deviceId, "totalActivePower");
  624. } else {
  625. gridmeter = await getstationrecord(data.electricMeter[i].deviceId, "totalActivePower");
  626. }
  627. }
  628. }
  629. if (true) {
  630. const { data } = await stationcolor(
  631. { startDateTime: value2.value[0], endDateTime: value2.value[1] },
  632. Singlevalue.value,
  633. emsDeviceId.value
  634. );
  635. stationcolorlist = data;
  636. }
  637. await getoperatingcurve(pcsdata, Cluster, Meter, gridmeter, stationcolorlist);
  638. // for (let index = 0; index < data.batteryStack.length; index++) {
  639. // getstationrecord(data.pcs[index].deviceId, "totalActivePower");
  640. // }
  641. };
  642. //
  643. const getstationrecord = async (id: string, codes: string) => {
  644. let obj = {
  645. startDateTime: value2.value[0],
  646. endDateTime: value2.value[1],
  647. deviceId: id,
  648. fieldCodes: codes
  649. };
  650. const { data } = await stationrecord(obj, Singlevalue.value, emsDeviceId.value);
  651. // if (false) {
  652. // getoperatingcurve(data.gridPower, data.storedPower);
  653. // }
  654. return data;
  655. };
  656. const getoperatingcurve = (pcsdata: any, Cluster: any, Meter: any, gridmeter: any, stationcolorlist: any[]) => {
  657. const dateLists = stationcolorlist.map(function (item: any) {
  658. if (item.periodType == 1) {
  659. return [
  660. {
  661. xAxis: item.startTime,
  662. itemStyle: {
  663. color: "#f9efee"
  664. }
  665. },
  666. {
  667. xAxis: item.endTime
  668. }
  669. ];
  670. } else if (item.periodType == 2) {
  671. return [
  672. {
  673. xAxis: item.startTime,
  674. itemStyle: {
  675. color: "#fdfbf9"
  676. }
  677. },
  678. {
  679. xAxis: item.endTime
  680. }
  681. ];
  682. } else if (item.periodType == 3) {
  683. return [
  684. {
  685. xAxis: item.startTime,
  686. itemStyle: {
  687. color: "#f6fcff"
  688. }
  689. },
  690. {
  691. xAxis: item.endTime
  692. }
  693. ];
  694. } else if (item.periodType == 4) {
  695. return [
  696. {
  697. xAxis: item.startTime,
  698. itemStyle: {
  699. color: "#f8fef9"
  700. }
  701. },
  702. {
  703. xAxis: item.endTime
  704. }
  705. ];
  706. }
  707. });
  708. const operatingcurvevalue = echarts.init(operatingcurve.value);
  709. window.addEventListener(
  710. "resize",
  711. () => {
  712. operatingcurvevalue.resize();
  713. },
  714. false
  715. );
  716. let option = {
  717. grid: {
  718. left: "2%",
  719. right: "4%",
  720. bottom: "6%",
  721. backgroundColor: "#222222", // 设置折线图的背景色
  722. containLabel: true // 是否包含坐标轴的刻度标签
  723. },
  724. legend: {
  725. bottom: 0
  726. },
  727. title: [],
  728. tooltip: {
  729. trigger: "axis"
  730. },
  731. xAxis: {
  732. data: pcsdata.ts,
  733. type: "category",
  734. axisTick: {
  735. show: false // 这里设置为false隐藏X轴刻度线
  736. }
  737. },
  738. yAxis: [
  739. {
  740. type: "value",
  741. name: "功率/kW",
  742. show: true,
  743. id: 0
  744. // interval: 50
  745. },
  746. {
  747. type: "value",
  748. name: "SOC/%",
  749. show: true,
  750. min: 0,
  751. max: 100,
  752. // interval: 10,
  753. id: 1,
  754. axisLabel: {
  755. formatter: "{value} %"
  756. }
  757. },
  758. {
  759. type: "value",
  760. name: "电压/V",
  761. show: true,
  762. min: 0,
  763. max: 100,
  764. position: "right", // 将第三个单位放在右边
  765. offset: 80, // 调整位置,使其与第二个单位错开
  766. id: 2,
  767. axisLabel: {
  768. formatter: "{value} %" // 设置轴标签格式
  769. }
  770. }
  771. ],
  772. series: [
  773. {
  774. name: pcsdata.deviceName + "_有功功率",
  775. type: "line",
  776. showSymbol: false,
  777. smooth: true,
  778. data: pcsdata.totalActivePower,
  779. // color: "rgba(190,233,197, 0.2)"
  780. markArea: {
  781. itemStyle: {
  782. normal: {
  783. color: "rgba(217 217 217 / 0.5)" // 默认区域的背景颜色
  784. },
  785. emphasis: {
  786. color: "rgba(217 217 217 / 0.5)" // 鼠标悬浮时的背景颜色
  787. }
  788. },
  789. data: dateLists
  790. }
  791. },
  792. {
  793. name: Meter.deviceName + "_有功功率",
  794. type: "line",
  795. showSymbol: false,
  796. data: Meter.totalActivePower
  797. },
  798. // {
  799. // name: gridmeter.deviceName + "_有功功率",
  800. // type: "line",
  801. // data: gridmeter.totalActivePower
  802. // },
  803. {
  804. name: Cluster.deviceName + "_SOC",
  805. type: "line",
  806. showSymbol: false,
  807. data: Cluster.soc
  808. },
  809. {
  810. name: Cluster.deviceName + "_单体最高电压",
  811. type: "line",
  812. showSymbol: false,
  813. data: Cluster.maxCellVoltage
  814. },
  815. {
  816. name: Cluster.deviceName + "_单体最低电压",
  817. type: "line",
  818. showSymbol: false,
  819. // stack: "Total",
  820. data: Cluster.minCellVoltage
  821. }
  822. ]
  823. };
  824. //gridmeter
  825. operatingcurvevalue.setOption(option, false);
  826. };
  827. // 实时电量收益
  828. const pickervalue = ref();
  829. const incomedata = ref();
  830. const pickerincome = async (val: any) => {
  831. if (val == null) {
  832. pickervalue.value = "";
  833. } else {
  834. pickervalue.value = formatDate(val);
  835. }
  836. };
  837. const onreset = () => {
  838. const current = localStorage.getItem("currentDate");
  839. pickervalue.value = current;
  840. gatrevenue();
  841. };
  842. const gatrevenue = async () => {
  843. let obj = {
  844. date: pickervalue.value
  845. };
  846. const { data } = await postelectricityrevenue(obj, Singlevalue.value, emsDeviceId.value);
  847. incomedata.value = data;
  848. };
  849. onUnmounted(() => {
  850. clearInterval(intervalID.value);
  851. });
  852. onMounted(() => {
  853. const current = localStorage.getItem("currentDate");
  854. if (current) {
  855. pickervalue.value = current;
  856. }
  857. // 获取过去 7 天的日期
  858. const today = new Date();
  859. const currentHour = today.getHours();
  860. const currentMinute = today.getMinutes();
  861. // 格式化小时、分钟和秒,确保它们始终有两位数
  862. const formattedHour = currentHour < 10 ? "0" + currentHour : currentHour;
  863. const formattedMinute = currentMinute < 10 ? "0" + currentMinute : currentMinute;
  864. // 拼接成 HH:MM:SS 的格式
  865. const currentTime = `${formattedHour}:${formattedMinute}`;
  866. value2.value = [current + " " + "00:00", current + " " + currentTime];
  867. poststationstationName();
  868. });
  869. </script>
  870. <style scoped lang="scss">
  871. @import "./index.scss";
  872. </style>