src/views/costAccounting/energyCosts/index.vue
@@ -112,7 +112,7 @@
            <div class="kpi-left">
              <div class="kpi-label">总能耗成本</div>
              <div class="kpi-value">
                ¥{{ formatMoney(animatedOverview.totalCost) }}
                ¥{{ formatMoney(animatedOverview.totalEnergyCost) }}
              </div>
              <div class="kpi-meta">
                <span
@@ -143,7 +143,7 @@
              <button
                class="kpi-action"
                type="button"
                @click="copyKpi('totalCost')"
                @click="copyKpi('totalEnergyCost')"
              >
                复制
              </button>
@@ -165,7 +165,7 @@
            <div class="kpi-left">
              <div class="kpi-label">生产能耗成本</div>
              <div class="kpi-value">
                ¥{{ formatMoney(animatedOverview.productionCost) }}
                ¥{{ formatMoney(animatedOverview.productEnergyCost) }}
              </div>
              <div class="kpi-meta">
                <span
@@ -196,7 +196,7 @@
              <button
                class="kpi-action"
                type="button"
                @click="copyKpi('productionCost')"
                @click="copyKpi('productEnergyCost')"
              >
                复制
              </button>
@@ -218,7 +218,7 @@
            <div class="kpi-left">
              <div class="kpi-label">办公能耗成本</div>
              <div class="kpi-value">
                ¥{{ formatMoney(animatedOverview.officeCost) }}
                ¥{{ formatMoney(animatedOverview.officeEnergyCost) }}
              </div>
              <div class="kpi-meta">
                <span
@@ -249,7 +249,7 @@
              <button
                class="kpi-action"
                type="button"
                @click="copyKpi('officeCost')"
                @click="copyKpi('officeEnergyCost')"
              >
                复制
              </button>
@@ -270,7 +270,7 @@
            <div class="kpi-left">
              <div class="kpi-label">平均成本</div>
              <div class="kpi-value">
                ¥{{ formatMoney(animatedOverview.avgCost) }}
                ¥{{ formatMoney(animatedOverview.averageEnergyCost) }}
                <span class="kpi-unit"
                  >/{{ statisticsType === "day" ? "日" : "月" }}</span
                >
@@ -286,7 +286,7 @@
              <button
                class="kpi-action"
                type="button"
                @click="copyKpi('avgCost')"
                @click="copyKpi('averageEnergyCost')"
              >
                复制
              </button>
@@ -465,23 +465,23 @@
                  </div>
                </el-card>
              </el-col>
              <!-- <el-col :xs="24" :lg="12">
              <el-col :xs="24" :lg="12">
                <el-card class="chart-card" shadow="never">
                  <template #header>
                    <div class="chart-head">
                      <span class="chart-title">能耗单价对比</span>
                      <span class="chart-title">能耗用量对比</span>
                      <div class="chart-tools" @click.stop>
                        <button
                          class="chart-tool"
                          type="button"
                          @click="downloadChart('price', '能耗单价对比')"
                          @click="downloadChart('consumption', '能耗用量对比')"
                        >
                          下载
                        </button>
                        <button
                          class="chart-tool"
                          type="button"
                          @click="openBigChart('price', '能耗单价对比')"
                          @click="openBigChart('consumption', '能耗用量对比')"
                        >
                          大图
                        </button>
@@ -489,12 +489,12 @@
                    </div>
                  </template>
                  <div
                    ref="priceChartWrap"
                    ref="consumptionChartWrap"
                    class="chart-wrap"
                    v-loading="tableLoading"
                  >
                    <div
                      ref="priceChart"
                      ref="consumptionChart"
                      class="chart-content"
                      v-show="hasTableData"
                    ></div>
@@ -503,7 +503,7 @@
                    </div>
                  </div>
                </el-card>
              </el-col> -->
              </el-col>
            </el-row>
          </div>
        </transition>
@@ -574,7 +574,7 @@
          sortable="custom"
        />
        <el-table-column
          prop="energyType"
          prop="energyTyep"
          label="能耗类型"
          width="100"
          align="center"
@@ -583,8 +583,8 @@
          filter-placement="bottom-end"
        >
          <template #default="scope">
            <el-tag :type="getEnergyTypeType(scope.row.energyType)">
              {{ scope.row.energyType }}
            <el-tag :type="getEnergyTypeType(scope.row.energyTyep)">
              {{ scope.row.energyTyep }}
            </el-tag>
          </template>
        </el-table-column>
@@ -598,28 +598,28 @@
          filter-placement="bottom-end"
        >
          <template #default="scope">
            <el-tag :type="scope.row.type === '生产' ? 'primary' : 'info'">
            <el-tag :type="scope.row.type === '生产' ? 'primary' : 'warning'">
              {{ scope.row.type }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column prop="consumption" label="用量" align="right">
        <el-table-column prop="dosage" label="用量" align="right">
          <template #default="scope">
            <span class="consumption-value">{{
              formatNumber(scope.row.consumption, 2)
              formatNumber(scope.row.dosage, 2)
            }}</span>
            <span class="consumption-unit">{{ scope.row.unit }}</span>
          </template>
        </el-table-column>
        <el-table-column
          prop="price"
          prop="unitPrice"
          label="单价(元)"
          align="right"
          sortable="custom"
        >
          <template #default="scope">
            <span class="price-value">{{
              formatNumber(scope.row.price, 2)
              formatNumber(scope.row.unitPrice, 2)
            }}</span>
          </template>
        </el-table-column>
@@ -674,7 +674,7 @@
} from "@element-plus/icons-vue";
import * as echarts from "echarts";
// import { energyCostStatistics } from "@/api/costAccounting/energyCosts";
import { energyConsumptionDetailStatistics } from "@/api/energyManagement/energyType";
import { energyConsumptionDetailAccount } from "@/api/energyManagement/energyType";
// 统计维度:day-按日,month-按月
const statisticsType = ref("day");
@@ -705,18 +705,18 @@
// 统计概览
const overview = reactive({
  totalCost: "0.00",
  productionCost: "0.00",
  officeCost: "0.00",
  avgCost: "0.00",
  totalEnergyCost: "0.00",
  productEnergyCost: "0.00",
  officeEnergyCost: "0.00",
  averageEnergyCost: "0.00",
});
const selectedKpi = ref("all"); // all | production | office
const animatedOverview = reactive({
  totalCost: 0,
  productionCost: 0,
  officeCost: 0,
  avgCost: 0,
  totalEnergyCost: 0,
  productEnergyCost: 0,
  officeEnergyCost: 0,
  averageEnergyCost: 0,
});
const formatMoney = (v) => {
@@ -754,10 +754,10 @@
watch(
  () => ({ ...overview }),
  (val) => {
    animateNumber("totalCost", Number.parseFloat(val.totalCost));
    animateNumber("productionCost", Number.parseFloat(val.productionCost));
    animateNumber("officeCost", Number.parseFloat(val.officeCost));
    animateNumber("avgCost", Number.parseFloat(val.avgCost));
    animateNumber("totalEnergyCost", Number.parseFloat(val.totalEnergyCost));
    animateNumber("productEnergyCost", Number.parseFloat(val.productEnergyCost));
    animateNumber("officeEnergyCost", Number.parseFloat(val.officeEnergyCost));
    animateNumber("averageEnergyCost", Number.parseFloat(val.averageEnergyCost));
  },
  { deep: true, immediate: true }
);
@@ -846,10 +846,10 @@
const copyKpi = async (field) => {
  const map = {
    totalCost: animatedOverview.totalCost,
    productionCost: animatedOverview.productionCost,
    officeCost: animatedOverview.officeCost,
    avgCost: animatedOverview.avgCost,
    totalEnergyCost: animatedOverview.totalEnergyCost,
    productEnergyCost: animatedOverview.productEnergyCost,
    officeEnergyCost: animatedOverview.officeEnergyCost,
    averageEnergyCost: animatedOverview.averageEnergyCost,
  };
  const raw = map[field];
  const text = `¥${formatMoney(raw)}`;
@@ -875,13 +875,13 @@
  if (key === "cost") return costChartInstance;
  if (key === "type") return typeChartInstance;
  if (key === "purpose") return purposeChartInstance;
  if (key === "price") return priceChartInstance;
  if (key === "consumption") return consumptionChartInstance;
  return null;
};
const ensurePanelForChart = (key) => {
  if (key === "cost" || key === "type") chartPanel.value = "core";
  if (key === "purpose" || key === "price") chartPanel.value = "advanced";
  if (key === "purpose" || key === "consumption") chartPanel.value = "advanced";
};
const downloadChart = (key, title) => {
@@ -997,7 +997,7 @@
  { text: "办公", value: "办公" },
];
const filterEnergyType = (value, row) => row.energyType === value;
const filterEnergyType = (value, row) => row.energyTyep === value;
const filterEnergyPurpose = (value, row) => row.type === value;
// 分页
@@ -1011,12 +1011,12 @@
const costChart = ref(null);
const typeChart = ref(null);
const purposeChart = ref(null);
const priceChart = ref(null);
const consumptionChart = ref(null);
const costChartWrap = ref(null);
const typeChartWrap = ref(null);
const purposeChartWrap = ref(null);
const priceChartWrap = ref(null);
const consumptionChartWrap = ref(null);
const tableAnchor = ref(null);
@@ -1044,7 +1044,7 @@
let costChartInstance = null;
let typeChartInstance = null;
let purposeChartInstance = null;
let priceChartInstance = null;
let consumptionChartInstance = null;
// 图表区切换:core | advanced | none(点击当前选中可收起)
const chartPanel = ref("core");
@@ -1062,10 +1062,10 @@
  if (panel === "advanced") {
    if (purposeChart.value && !purposeChartInstance)
      purposeChartInstance = echarts.init(purposeChart.value);
    if (priceChart.value && !priceChartInstance)
      priceChartInstance = echarts.init(priceChart.value);
    if (consumptionChart.value && !consumptionChartInstance)
      consumptionChartInstance = echarts.init(consumptionChart.value);
    if (purposeChartInstance) updatePurposeChart();
    if (priceChartInstance) updatePriceChart();
    if (consumptionChartInstance) updateConsumptionChart();
  }
};
@@ -1331,26 +1331,32 @@
  purposeChartInstance.setOption(option);
};
// 更新能耗单价对比图
const updatePriceChart = () => {
// 更新能耗用量对比图
const updateConsumptionChart = () => {
  const data = tableData.value;
  const priceData = {};
  const consumptionData = {};
  data.forEach((item) => {
    if (!priceData[item.energyType]) {
      priceData[item.energyType] = {
    if (!consumptionData[item.energyType]) {
      consumptionData[item.energyType] = {
        生产: 0,
        办公: 0,
      };
    }
    if (priceData[item.energyType].hasOwnProperty(item.type)) {
      priceData[item.energyType][item.type] = parseFloat(item.price);
    if (consumptionData[item.energyType].hasOwnProperty(item.type)) {
      consumptionData[item.energyType][item.type] = parseFloat(
        item.consumption
      );
    }
  });
  const energyTypes = Object.keys(priceData);
  const productionPrices = energyTypes.map((type) => priceData[type].生产);
  const officePrices = energyTypes.map((type) => priceData[type].办公);
  const energyTypes = Object.keys(consumptionData);
  const productionConsumptions = energyTypes.map(
    (type) => consumptionData[type].生产
  );
  const officeConsumptions = energyTypes.map(
    (type) => consumptionData[type].办公
  );
  const option = {
    tooltip: {
@@ -1364,7 +1370,7 @@
        "box-shadow: 0 14px 40px rgba(15,23,42,.14); border-radius: 12px;",
    },
    legend: {
      data: ["生产能耗单价", "办公能耗单价"],
      data: ["生产能耗用量", "办公能耗用量"],
      top: 0,
      right: 10,
      textStyle: { color: "rgba(15, 23, 42, 0.62)" },
@@ -1385,7 +1391,7 @@
    },
    yAxis: {
      type: "value",
      name: "单价(元)",
      name: "用量",
      nameTextStyle: { color: "rgba(15, 23, 42, 0.58)" },
      axisLabel: { color: "rgba(15, 23, 42, 0.58)" },
      axisLine: { show: false },
@@ -1393,9 +1399,9 @@
    },
    series: [
      {
        name: "生产能耗单价",
        name: "生产能耗用量",
        type: "bar",
        data: productionPrices,
        data: productionConsumptions,
        itemStyle: {
          color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
            { offset: 0, color: "#2f6fed" },
@@ -1405,9 +1411,9 @@
        },
      },
      {
        name: "办公能耗单价",
        name: "办公能耗用量",
        type: "bar",
        data: officePrices,
        data: officeConsumptions,
        itemStyle: {
          color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
            { offset: 0, color: "#16a34a" },
@@ -1418,7 +1424,7 @@
      },
    ],
  };
  priceChartInstance.setOption(option);
  consumptionChartInstance.setOption(option);
};
// 统计维度切换
@@ -1505,36 +1511,36 @@
  }
  // 调用接口获取数据
  energyConsumptionDetailStatistics(params)
  energyConsumptionDetailAccount(params)
    .then((res) => {
      if (res.code === 200) {
        const data = res.data;
        overview.totalCost = data.totalEnergyConsumption || "0";
        overview.productionCost = data.totalEnergyCost || "0";
        overview.avgCost = data.averageConsumption || "0";
        overview.officeCost = data.changeVite || 0;
        overview.totalEnergyCost = data.totalEnergyCost || "0";
        overview.productEnergyCost = data.productEnergyCost || "0";
        overview.officeEnergyCost = data.officeEnergyCost || "0";
        overview.averageEnergyCost = data.averageEnergyCost || "0";
        // 处理表格数据
        tableData.value = data.energyCostDtos || [];
        tableData.value = data.energyConsumptionDetailDtoList || [];
        page.total = tableData.value.length || 0;
      } else {
        ElMessage.error(res.message || "获取数据失败");
        tableData.value = [];
        page.total = 0;
        overview.totalCost = "0.00";
        overview.productionCost = "0.00";
        overview.officeCost = "0.00";
        overview.avgCost = "0.00";
        overview.totalEnergyCost = "0.00";
        overview.productEnergyCost = "0.00";
        overview.officeEnergyCost = "0.00";
        overview.averageEnergyCost = "0.00";
      }
    })
    .catch((err) => {
      ElMessage.error("获取数据异常");
      tableData.value = [];
      page.total = 0;
      overview.totalCost = "0.00";
      overview.productionCost = "0.00";
      overview.officeCost = "0.00";
      overview.avgCost = "0.00";
      overview.totalEnergyCost = "0.00";
      overview.productEnergyCost = "0.00";
      overview.officeEnergyCost = "0.00";
      overview.averageEnergyCost = "0.00";
    })
    .finally(() => {
      tableLoading.value = false;
@@ -1548,7 +1554,7 @@
    if (costChartInstance) updateCostChart();
    if (typeChartInstance) updateTypeChart();
    if (purposeChartInstance) updatePurposeChart();
    if (priceChartInstance) updatePriceChart();
    if (consumptionChartInstance) updateConsumptionChart();
  });
};
@@ -1600,7 +1606,7 @@
  costChartInstance && costChartInstance.resize();
  typeChartInstance && typeChartInstance.resize();
  purposeChartInstance && purposeChartInstance.resize();
  priceChartInstance && priceChartInstance.resize();
  consumptionChartInstance && consumptionChartInstance.resize();
};
onMounted(() => {
@@ -2739,4 +2745,4 @@
  max-height: 600px;
  opacity: 1;
}
</style>
</style>