Parcourir la source

[26110501] 光伏上传率统计页面: 场站(必选默认第一个)+起止日期(默认近7天)+查询/导出, 服务端分页表格(10行/页, 日期+9列上传率), 导出文件名光伏上传率统计_截止日.xlsx

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
taosj il y a 15 heures
Parent
commit
5836076816

+ 20 - 0
forecast-backend-vue/src/api/fileupload/reportLog.js

@@ -16,3 +16,23 @@ export function getReportLogFileContent(id) {
     method: 'get'
   })
 }
+
+// 查询光伏上传率统计(手动分页)
+export function listUploadRate(data) {
+  return request({
+    url: '/fileupload/reportLog/uploadRate/list',
+    method: 'post',
+    data
+  })
+}
+
+// 导出光伏上传率统计
+export function exportUploadRate(data) {
+  return request({
+    url: '/fileupload/reportLog/uploadRate/export',
+    method: 'post',
+    data,
+    responseType: 'blob',
+    timeout: 120000
+  })
+}

+ 194 - 0
forecast-backend-vue/src/views/ufo/electricity/statanalysis/uploadRateStat.vue

@@ -0,0 +1,194 @@
+<template>
+  <div class="upload-rate-stat-page">
+    <a-card :bordered="false">
+      <a-row :gutter="[12, 12]" align="middle">
+        <a-col :xs="24" :md="6">
+          <StationSelector v-model:value="query.stationCode" :options="stationOptions" :multiple="false" />
+        </a-col>
+        <a-col :xs="24" :md="5">
+          <a-date-picker
+            v-model:value="query.startTime"
+            class="full-control"
+            format="YYYY-MM-DD"
+            placeholder="起始时间"
+            value-format="YYYY-MM-DD"
+          />
+        </a-col>
+        <a-col :xs="24" :md="5">
+          <a-date-picker
+            v-model:value="query.endTime"
+            class="full-control"
+            format="YYYY-MM-DD"
+            placeholder="截止时间"
+            value-format="YYYY-MM-DD"
+          />
+        </a-col>
+        <a-col :xs="24" :md="8">
+          <a-space>
+            <a-button type="primary" :loading="loading" :disabled="!queryValid" @click="handleQuery">确认</a-button>
+            <a-button :loading="exporting" :disabled="!queryValid" @click="handleExport">导出</a-button>
+          </a-space>
+        </a-col>
+      </a-row>
+    </a-card>
+    <a-card :bordered="false" class="content-card">
+      <a-table
+        :columns="columns"
+        :data-source="rows"
+        :loading="loading"
+        :pagination="pagination"
+        :scroll="{x: 1760}"
+        row-key="date"
+        size="middle"
+        @change="handleTableChange"
+      />
+    </a-card>
+  </div>
+</template>
+
+<script setup name="UploadRateStat">
+import {computed, onMounted, reactive, ref} from 'vue';
+import {message} from 'ant-design-vue';
+import dayjs from 'dayjs';
+import {saveAs} from 'file-saver';
+import {blobValidate} from '@/utils/bearjia';
+import {listStation} from '@/api/config/station';
+import {exportUploadRate, listUploadRate} from '@/api/fileupload/reportLog';
+import StationSelector from '../components/StationSelector.vue';
+
+const loading = ref(false);
+const exporting = ref(false);
+const stationOptions = ref([]);
+const rows = ref([]);
+const pagination = reactive({
+  current: 1,
+  pageSize: 10,
+  total: 0,
+  showSizeChanger: true,
+  showTotal: (total) => `共 ${total} 天`
+});
+const query = reactive({
+  stationCode: undefined,
+  startTime: dayjs().subtract(7, 'day').format('YYYY-MM-DD'),
+  endTime: dayjs().format('YYYY-MM-DD')
+});
+
+const queryValid = computed(() => {
+  if (!query.startTime || !query.endTime) return false;
+  const start = dayjs(query.startTime);
+  const end = dayjs(query.endTime);
+  if (!start.isValid() || !end.isValid()) return false;
+  return !start.isAfter(end);
+});
+
+const columns = [
+  {title: '日期时间', dataIndex: 'date', width: 120},
+  {title: '超短期文件上传率(%)', dataIndex: 'supershortRate', width: 170},
+  {title: '短期文件上传率(%)', dataIndex: 'shortRate', width: 160},
+  {title: '中期文件上传率(%)', dataIndex: 'mediumRate', width: 160},
+  {title: '环境检测仪数据上传率(%)', dataIndex: 'envlDetectorRate', width: 190},
+  {title: '逆变器运行信息文件上传率(%)', dataIndex: 'inverterOperationRate', width: 210},
+  {title: '升压变数据上传率(%)', dataIndex: 'boosterTransformerRate', width: 180},
+  {title: '理论功率文件上传率(%)', dataIndex: 'theoreticalPowerRate', width: 190},
+  {title: '数值天气预报文件上传率(%)', dataIndex: 'numericalWeatherRate', width: 200},
+  {title: '发电计划文件上传率(%)', dataIndex: 'powerGenerationPlanRate', width: 180}
+];
+
+const loadStationOptions = async () => {
+  const res = await listStation({pageNum: 1, pageSize: 500});
+  const list = (res && res.rows) || [];
+  stationOptions.value = list.map((item) => ({label: item.stationName, value: item.stationCode}));
+  if (!query.stationCode && stationOptions.value.length) {
+    query.stationCode = stationOptions.value[0].value;
+  }
+};
+
+const fetchList = async (pageNum, pageSize) => {
+  if (!query.stationCode) {
+    message.warning('请先选择场站');
+    return;
+  }
+  loading.value = true;
+  try {
+    const res = await listUploadRate({
+      stationCode: query.stationCode,
+      startTime: query.startTime,
+      endTime: query.endTime,
+      pageNum,
+      pageSize
+    });
+    rows.value = res.rows || [];
+    pagination.total = res.total || 0;
+    pagination.current = pageNum;
+    pagination.pageSize = pageSize;
+  } catch (e) {
+    // request.js 已统一提示错误
+  } finally {
+    loading.value = false;
+  }
+};
+
+const handleQuery = () => {
+  if (!query.stationCode) {
+    message.warning('请先选择场站');
+    return;
+  }
+  if (!queryValid.value) return;
+  fetchList(1, pagination.pageSize);
+};
+
+const handleTableChange = (pag) => {
+  fetchList(pag.current, pag.pageSize);
+};
+
+const handleExport = async () => {
+  if (!query.stationCode) {
+    message.warning('请先选择场站');
+    return;
+  }
+  if (!queryValid.value) return;
+  exporting.value = true;
+  try {
+    const res = await exportUploadRate({
+      stationCode: query.stationCode,
+      startTime: query.startTime,
+      endTime: query.endTime
+    });
+    const isFile = await blobValidate(res);
+    if (isFile) {
+      saveAs(new Blob([res]), `光伏上传率统计_${query.endTime.replaceAll('-', '')}.xlsx`);
+      message.success('导出成功');
+    } else {
+      const text = await res.text();
+      let msg = '导出失败';
+      try {
+        msg = JSON.parse(text)?.msg || msg;
+      } catch (e) {
+        /* ignore */
+      }
+      message.error(msg);
+    }
+  } finally {
+    exporting.value = false;
+  }
+};
+
+onMounted(async () => {
+  await loadStationOptions();
+  handleQuery();
+});
+</script>
+
+<style lang="less" scoped>
+.upload-rate-stat-page {
+  padding: 16px;
+}
+
+.full-control {
+  width: 100%;
+}
+
+.content-card {
+  margin-top: 16px;
+}
+</style>