yyb
4 小时以前 3bc464bb272c2737e794a886ba89234fdacf6bf5
src/views/costAccounting/stdVsActCostAnalysis/index.vue
@@ -118,9 +118,25 @@
        </div>
      </template>
      <div class="chart-wrap">
        <div class="chart-tools chart-tools-inline" @click.stop>
          <button class="chart-tool" type="button" @click="openLargeChart">查看大图</button>
          <button class="chart-tool" type="button" @click="downloadChartImage">下载图表</button>
        </div>
        <div ref="chartRef" class="chart-content"></div>
      </div>
    </el-card>
    <el-dialog
      v-model="largeChartVisible"
      title="标准/实际成本对比大图"
      width="88%"
      top="6vh"
      destroy-on-close
      @opened="initLargeChart"
      @closed="disposeLargeChart"
    >
      <div ref="largeChartRef" class="large-chart-content"></div>
    </el-dialog>
    <el-card class="table-card" shadow="never">
      <template #header>
@@ -191,7 +207,11 @@
const uploadRef = ref();
const chartRef = ref(null);
const largeChartRef = ref(null);
let chartInstance = null;
let largeChartInstance = null;
const largeChartVisible = ref(false);
const currentChartOption = ref(null);
const actualCostSource = ref([
  { month: "2026-01", category: "瓷砖", costType: "能耗成本", actualCost: 182000 },
@@ -298,10 +318,9 @@
  return { xAxis, standard, actual, diffRate };
};
const updateChart = () => {
  if (!chartInstance) return;
const buildChartOption = () => {
  const { xAxis, standard, actual, diffRate } = getChartData();
  chartInstance.setOption({
  return {
    tooltip: {
      trigger: "axis",
      axisPointer: { type: "shadow" },
@@ -363,7 +382,14 @@
        lineStyle: { width: 2 },
      },
    ],
  });
  };
};
const updateChart = () => {
  const option = buildChartOption();
  currentChartOption.value = option;
  chartInstance?.setOption(option);
  largeChartInstance?.setOption(option);
};
const normalizeCostType = (value) => {
@@ -501,6 +527,54 @@
const handleResize = () => {
  chartInstance?.resize?.();
  largeChartInstance?.resize?.();
};
const openLargeChart = () => {
  if (!tableData.value.length) {
    ElMessage.warning("暂无图表数据可查看");
    return;
  }
  largeChartVisible.value = true;
};
const initLargeChart = () => {
  nextTick(() => {
    if (!largeChartRef.value) return;
    if (!largeChartInstance) {
      largeChartInstance = echarts.init(largeChartRef.value);
    }
    if (currentChartOption.value) {
      largeChartInstance.setOption(currentChartOption.value);
    } else {
      updateChart();
    }
  });
};
const disposeLargeChart = () => {
  largeChartInstance?.dispose?.();
  largeChartInstance = null;
};
const downloadChartImage = () => {
  const sourceChart = chartInstance || largeChartInstance;
  if (!sourceChart) {
    ElMessage.warning("图表尚未加载完成");
    return;
  }
  const url = sourceChart.getDataURL({
    type: "png",
    pixelRatio: 2,
    backgroundColor: "#ffffff",
  });
  const link = document.createElement("a");
  link.href = url;
  link.download = `标准实际成本对比图_${new Date().toISOString().slice(0, 10)}.png`;
  document.body.appendChild(link);
  link.click();
  document.body.removeChild(link);
  ElMessage.success("图表下载成功");
};
onMounted(() => {
@@ -517,6 +591,7 @@
  window.removeEventListener("resize", handleResize);
  chartInstance?.dispose?.();
  chartInstance = null;
  disposeLargeChart();
});
watch(tableData, () => {
@@ -687,6 +762,8 @@
}
.chart-wrap {
  position: relative;
  padding-top: 34px;
  border-radius: 12px;
  overflow: hidden;
}
@@ -695,6 +772,43 @@
  height: 360px;
}
.chart-tools {
  display: flex;
  align-items: center;
  gap: 8px;
}
.chart-tools-inline {
  position: absolute;
  top: 4px;
  right: 6px;
  z-index: 2;
}
.chart-tool {
  font-size: 11px;
  font-weight: 650;
  line-height: 1;
  padding: 6px 10px;
  border-radius: 10px;
  border: 1px solid rgba(15, 23, 42, 0.1);
  background: rgba(255, 255, 255, 0.78);
  color: rgba(15, 23, 42, 0.72);
  cursor: pointer;
  transition: background-color 0.16s ease, border-color 0.16s ease, transform 0.16s ease;
}
.chart-tool:hover {
  background: rgba(47, 111, 237, 0.08);
  border-color: rgba(47, 111, 237, 0.22);
  transform: translateY(-1px);
}
.large-chart-content {
  height: 70vh;
  min-height: 520px;
}
.pagination-container {
  display: flex;
  justify-content: flex-end;