当前位置: 首页 > article >正文

vue3+AntvS2基本使用与导出excel

在这里插入图片描述
在这里插入图片描述

安装 antv/s2 和 antv/s2-vue

npm i @antv/s2
npm i @antv/s2-vue
react项目自行更换 antv/s2-vue

在vue3里使用

新建一个名为 PageThreeLook.vue 的文件。

由于数据有时很大,所以这边是在后端返回数据后就先计算,然后再渲染的。计算是再 getPageList()方法里进行

<!-- 预算与实际---页面 -->
<template>
  <div class="home">
    <el-container class="page-main">
      <el-header height="auto">
        <div
          v-show="queryParams.toolQuery.queryParamsShow"
          style="transition: all 0.3s; overflow: hidden"
        >
          搜索条件
        </div>
        <div
          style="
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin: 5px 0;
          "
        >
          <div style="display: flex; width: 50%; align-items: center">
            <span style="font-weight: 900; font-size: 12px; color: #000">{{
              queryParams.PageName
            }}</span>---假数据
          </div>
          <div style="width: 50%; display: flex; overflow-x: auto">
            <el-button type="primary" size="small" @click="searchData"
              >搜索</el-button
            >
            <el-button
              style="margin-left: 10px"
              type="success"
              size="small"
              @click="click_look"
              >当前页导出excel</el-button
            >
          </div>
        </div>
      </el-header>
      <el-main
        :style="{
          height: queryParams.toolQuery.queryParamsShow
            ? 'calc(100% - 200px)'
            : 'calc(100% - 180px)',
        }"
      >
        <div v-if="!SAut.show">
          需要需要加定时器,没有数据就不显示,有数据了在显示
        </div>
        <div v-else style="width: 100%; height: 100%">
          <SheetComponent
            ref="tableRef"
            :dataCfg="SAut.s2DataConfig"
            :options="SAut.s2Options"
            :adaptive="{
              width: true,
              height: true,
            }"
            loading
          />
        </div>
      </el-main>
    </el-container>

    <el-drawer
      v-model="Look.show"
      title="自定义列表"
      direction="rtl"
      size="90%"
      :show-close="false"
      destroy-on-close
      :with-header="false"
    >
      <div style="width: 100%; height: 100vh; overflow: auto">
        <ThreePageXiangQingLook
          :ArrayList="Look.list"
          @submitOK="onSubmitOK_Look"
        />
      </div>
    </el-drawer>
  </div>
</template>
<script setup>
import { ref, onMounted } from "vue";
import { useRouter, useRoute, onBeforeRouteLeave } from "vue-router";
import { SelectAnnualSummary } from "../../api/index";
import { ElNotification, ElDatePicker } from "element-plus";
import ThreePageXiangQingLook from "./ThreeXiangQingLook.vue";
import { Aggregation, PivotSheet, QueryDataType, VALUE_FIELD } from "@antv/s2";
import { SheetComponent } from "@antv/s2-vue";
import "@antv/s2-vue/dist/style.min.css";

const router = useRouter();
const route = useRoute();

const tableRef = ref(null);
const SAut = ref({
  show: false,
  s2DataConfig: null,
  s2Options: null,
});

const antv_Demo = (list) => {
  setTimeout(() => {
    SAut.value.show = true;

    const s2DataConfig = {
      fields: {
        rows: ["deptname", "zjzmoney", "type"],
        columns: [],
        values: [
          "januaryMoney",
          "februaryMoney",
          "marchMoney",
          "aprilMoney",
          "mayMoney",
          "juneMoney",
          "julyMoney",
          "augustMoney",
          "septemberMoney",
          "octoberMoney",
          "novemberMoney",
          "decemberMoney",
          "noMoney",
          "HeJi",
        ],
      },
      meta: [
        {
          field: "deptname",
          name: "部门",
        },
        {
          field: "zjzmoney",
          name: "年度目标",
        },
        {
          field: "type",
          name: "类别",
        },
        {
          field: "januaryMoney",
          name: "1月",
        },
        {
          field: "februaryMoney",
          name: "2月",
        },
        {
          field: "januaryMoney",
          name: "1月",
        },
        {
          field: "marchMoney",
          name: "3月",
        },
        {
          field: "aprilMoney",
          name: "4月",
        },
        {
          field: "mayMoney",
          name: "5月",
        },
        {
          field: "juneMoney",
          name: "6月",
        },
        {
          field: "julyMoney",
          name: "7月",
        },
        {
          field: "augustMoney",
          name: "8月",
        },
        {
          field: "septemberMoney",
          name: "9月",
        },
        {
          field: "octoberMoney",
          name: "10月",
        },
        {
          field: "novemberMoney",
          name: "11月",
        },
        {
          field: "decemberMoney",
          name: "12月",
        },
        {
          field: "noMoney",
          name: "未完成年度目标额度",
        },
        {
          field: "HeJi",
          name: "全年合计",
        },
      ],
      data: list,
    };
    const s2Options = {
      width: 600,
      height: 480,
      conditions: {
        text: [
          {
            field: "januaryMoney",
            mapping(fieldValue, data) {
              // 根据单元格数据动态标记
              if (data.januaryMoney < 0) {
                return {
                  fill: "#fd0101",
                };
              }
              return {
                fill: "#000",
              };
            },
          },
          {
            field: "februaryMoney",
            mapping(fieldValue, data) {
              // 根据单元格数据动态标记
              if (data.februaryMoney < 0) {
                return {
                  fill: "#fd0101",
                };
              }
              return {
                fill: "#000",
              };
            },
          },
          {
            field: "marchMoney",
            mapping(fieldValue, data) {
              // 根据单元格数据动态标记
              if (data.marchMoney < 0) {
                return {
                  fill: "#fd0101",
                };
              }
              return {
                fill: "#000",
              };
            },
          },
          {
            field: "aprilMoney",
            mapping(fieldValue, data) {
              // 根据单元格数据动态标记
              if (data.aprilMoney < 0) {
                return {
                  fill: "#fd0101",
                };
              }
              return {
                fill: "#000",
              };
            },
          },
          {
            field: "mayMoney",
            mapping(fieldValue, data) {
              // 根据单元格数据动态标记
              if (data.mayMoney < 0) {
                return {
                  fill: "#fd0101",
                };
              }
              return {
                fill: "#000",
              };
            },
          },
          {
            field: "juneMoney",
            mapping(fieldValue, data) {
              // 根据单元格数据动态标记
              if (data.juneMoney < 0) {
                return {
                  fill: "#fd0101",
                };
              }
              return {
                fill: "#000",
              };
            },
          },
          {
            field: "julyMoney",
            mapping(fieldValue, data) {
              // 根据单元格数据动态标记
              if (data.julyMoney < 0) {
                return {
                  fill: "#fd0101",
                };
              }
              return {
                fill: "#000",
              };
            },
          },
          {
            field: "augustMoney",
            mapping(fieldValue, data) {
              // 根据单元格数据动态标记
              if (data.augustMoney < 0) {
                return {
                  fill: "#fd0101",
                };
              }
              return {
                fill: "#000",
              };
            },
          },
          {
            field: "septemberMoney",
            mapping(fieldValue, data) {
              // 根据单元格数据动态标记
              if (data.septemberMoney < 0) {
                return {
                  fill: "#fd0101",
                };
              }
              return {
                fill: "#000",
              };
            },
          },
          {
            field: "octoberMoney",
            mapping(fieldValue, data) {
              // 根据单元格数据动态标记
              if (data.octoberMoney < 0) {
                return {
                  fill: "#fd0101",
                };
              }
              return {
                fill: "#000",
              };
            },
          },
          {
            field: "novemberMoney",
            mapping(fieldValue, data) {
              // 根据单元格数据动态标记
              if (data.novemberMoney < 0) {
                return {
                  fill: "#fd0101",
                };
              }
              return {
                fill: "#000",
              };
            },
          },
          {
            field: "decemberMoney",
            mapping(fieldValue, data) {
              // 根据单元格数据动态标记
              if (data.decemberMoney < 0) {
                return {
                  fill: "#fd0101",
                };
              }
              return {
                fill: "#000",
              };
            },
          },
          {
            field: "noMoney",
            mapping(fieldValue, data) {
              // 根据单元格数据动态标记
              if (data.noMoney < 0) {
                return {
                  fill: "#fd0101",
                };
              }
              return {
                fill: "#000",
              };
            },
          },
          {
            field: "HeJi",
            mapping(fieldValue, data) {
              // 根据单元格数据动态标记
              if (data.HeJi < 0) {
                return {
                  fill: "#fd0101",
                };
              }
              return {
                fill: "#000",
              };
            },
          },
        ],
      },
    };

    SAut.value.s2DataConfig = s2DataConfig;
    SAut.value.s2Options = s2Options;
  }, 1000);
};
// 导出
const Look = ref({
  show: false,
  type: null,
  item: null,
  list: [],
});

const onSubmitOK_Look = (val) => {
  //console.log("关闭当前页面", val);
  Look.value.item = null;
  Look.value.type = null;
  Look.value.show = false;
};
const click_look = () => {
  Look.value.list = queryParams.value.tableConfig.tableData.all;
  setTimeout(() => {
    Look.value.show = true;
  }, 300);
};

const Look_Action = ref("look");
let queryParams = ref({
  PageName: "预算年汇总",
  action: false,
  Cookie_USER: null,
  loadingTxt: "",
  loading: {
    table: false,
  },
  tableConfig: {
    tableData: {
      all: [],
    },
    tableColumn: [
      {
        field: "deptname",
        show: true,
        label: "部门",
        width: "150",
        fixed: "left",
        sortable: false,
        overflowShow: false,
        disabled: true,
      },
      {
        field: "zjzmoney",
        show: true,
        label: "年度目标",
        width: "150",
        fixed: "left",
        sortable: false,
        overflowShow: false,
        disabled: true,
      },
      {
        field: "type",
        show: true,
        label: "类型",
        fixed: "left",
        width: "100",
        sortable: false,
        overflowShow: false,
        disabled: true,
      },
      {
        field: "januaryMoney",
        show: true,
        label: "1月",
        width: "200",
        sortable: false,
        overflowShow: false,
        disabled: true,
      },
      {
        field: "februaryMoney",
        show: true,
        label: "2月",
        width: "200",
        sortable: false,
        overflowShow: false,
        disabled: true,
      },
      {
        field: "marchMoney",
        show: true,
        label: "3月",
        width: "200",
        sortable: false,
        overflowShow: false,
        disabled: true,
      },
      {
        field: "aprilMoney",
        show: true,
        label: "4月",
        width: "200",
        sortable: false,
        overflowShow: false,
        disabled: true,
      },
      {
        field: "mayMoney",
        show: true,
        label: "5月",
        width: "200",
        sortable: false,
        overflowShow: false,
        disabled: true,
      },
      {
        field: "juneMoney",
        show: true,
        label: "6月",
        width: "200",
        sortable: false,
        overflowShow: false,
        disabled: true,
      },
      {
        field: "julyMoney",
        show: true,
        label: "7月",
        width: "200",
        sortable: false,
        overflowShow: false,
        disabled: true,
      },
      {
        field: "augustMoney",
        show: true,
        label: "8月",
        width: "200",
        sortable: false,
        overflowShow: false,
        disabled: true,
      },
      {
        field: "septemberMoney",
        show: true,
        label: "9月",
        width: "200",
        sortable: false,
        overflowShow: false,
        disabled: true,
      },
      {
        field: "octoberMoney",
        show: true,
        label: "10月",
        width: "200",
        sortable: false,
        overflowShow: false,
        disabled: true,
      },
      {
        field: "novemberMoney",
        show: true,
        label: "11月",
        width: "200",
        sortable: false,
        overflowShow: false,
        disabled: true,
      },
      {
        field: "decemberMoney",
        show: true,
        label: "12月",
        width: "200",
        sortable: false,
        overflowShow: false,
        disabled: true,
      },
      {
        field: "noMoney",
        show: true,
        label: "未完成年度目标额度",
        width: "130",
        fixed: "right",
        sortable: false,
        overflowShow: false,
        disabled: true,
      },
      {
        field: "HeJi",
        show: true,
        label: "全年合计",
        width: "130",
        fixed: "right",
        sortable: false,
        overflowShow: false,
        disabled: true,
      },
    ],
  },
  toolQuery: {
    queryParams: {
      sqksjs: null, //申请时间
      area: null, //部门
      actions: null,
      customername: null, //用工单位
    },
    queryParamsShow: true,
  },
  direction: 1,
});

function calculateTotals(data) {
  const totals = {};
  // 遍历原始数据
  data.forEach((item) => {
    const { deptname, type } = item;
    // 只处理非'合计'的项目
    if (deptname !== "合计") {
      // 初始化合计对象
      if (!totals[type]) {
        totals[type] = {
          deptname: "合计",
          type: type,
        };
      }
      // 动态累加金额字段
      Object.keys(item).forEach((key) => {
        // 跳过 deptname 和 type 字段
        if (key !== "deptname" && key !== "type") {
          totals[type][key] = (
            Number(totals[type][key] || 0) + Number(item[key])
          ).toFixed(2);
        } else if (key == "su") {
          totals[type][key] = item[key];
        }
      });
    }
  });
  // 将合计对象转换为数组
  const totalArray = Object.values(totals);
  // 返回原始数据和合计数据的合并结果
  return [...data, ...totalArray];
}
function val_Null_Undefined(val) {
  if (val === null || val === undefined || val === "") {
    return "空值";
  } else {
    return "正常值";
  }
}
const FN_NoMoney = (row) => {
  let zjzmoney = val_Null_Undefined(row.zjzmoney);
  let HeJi = val_Null_Undefined(row.HeJi);

  if (row.type == "差额" || row.type == "预算完成率") {
    return "/";
  }

  if (zjzmoney === "空值") {
    zjzmoney = 0;
  } else {
    zjzmoney = Number(row.zjzmoney) || 0;
  }
  if (HeJi === "空值") {
    HeJi = 0;
  } else {
    HeJi = Number(row.HeJi) || 0;
  }

  let a = zjzmoney - HeJi;
  // row.noMoney = Number(a.toFixed(2));
  return Number(a.toFixed(2));
};
// 列表初始化
const getPageList = () => {
  SAut.value.show = false;
  let obj = {
    dateTime: "2024-08",
    page: 1,
    limit: 100,
  };
  queryParams.value.loading.table = true;
  queryParams.value.loadingTxt = "加载中。。。";
  queryParams.value.tableConfig.tableData.all = [];
  window.setTimeout(() => {
    let TableList = [
      {
        type: "预算利润",
        deptname: "第一个板块",
        zjzmoney: 0.0,
        januaryMoney: 0.0,
        februaryMoney: 0.0,
        marchMoney: 0.0,
        aprilMoney: 0.0,
        mayMoney: 0.0,
        juneMoney: 0.0,
        julyMoney: 0.0,
        augustMoney: 0.0,
        septemberMoney: 0.0,
        octoberMoney: 0.0,
        novemberMoney: 0.0,
        decemberMoney: 0.0,
      },
      {
        type: "实际利润",
        deptname: "第一个板块",
        zjzmoney: 0.0,
        januaryMoney: -10.83,
        februaryMoney: -104.83,
        marchMoney: -10.83,
        aprilMoney: -100.83,
        mayMoney: 0.0,
        juneMoney: 0.0,
        julyMoney: 0.0,
        augustMoney: 0.0,
        septemberMoney: 0.0,
        octoberMoney: 0.0,
        novemberMoney: 0.0,
        decemberMoney: 0.0,
      },
      {
        type: "预算利润",
        deptname: "第二个板块",
        zjzmoney: 0.0,
        januaryMoney: 0.0,
        februaryMoney: 0.0,
        marchMoney: 0.0,
        aprilMoney: 0.0,
        mayMoney: 0.0,
        juneMoney: 0.0,
        julyMoney: 0.0,
        augustMoney: 0.0,
        septemberMoney: 0.0,
        octoberMoney: 0.0,
        novemberMoney: 0.0,
        decemberMoney: 0.0,
      },
      {
        type: "实际利润",
        deptname: "第二个板块",
        zjzmoney: 0.0,
        januaryMoney: -7099.17,
        februaryMoney: -79.17,
        marchMoney: -79.17,
        aprilMoney: -9.17,
        mayMoney: -99.17,
        juneMoney: -199.17,
        julyMoney: -299.73,
        augustMoney: 6832.13,
        septemberMoney: 0.0,
        octoberMoney: 0.0,
        novemberMoney: 0.0,
        decemberMoney: 0.0,
      },
      {
        type: "预算利润",
        deptname: "第三个板块",
        zjzmoney: 0.0,
        januaryMoney: 0.0,
        februaryMoney: 0.0,
        marchMoney: 0.0,
        aprilMoney: 0.0,
        mayMoney: 0.0,
        juneMoney: 0.0,
        julyMoney: 0.0,
        augustMoney: 0.0,
        septemberMoney: 831791.17,
        octoberMoney: 843707.26,
        novemberMoney: 0.0,
        decemberMoney: 0.0,
      },
      {
        type: "实际利润",
        deptname: "第三个板块",
        zjzmoney: 0.0,
        januaryMoney: 527144.27,
        februaryMoney: 1834.09,
        marchMoney: 17483.19,
        aprilMoney: 20503.38,
        mayMoney: 45261.39,
        juneMoney: 7233.9,
        julyMoney: 626.19,
        augustMoney: 428.76,
        septemberMoney: 0.0,
        octoberMoney: 0.0,
        novemberMoney: 0.0,
        decemberMoney: 0.0,
      },
      {
        type: "预算利润",
        deptname: "第四个板块",
        zjzmoney: 0.0,
        januaryMoney: 0.0,
        februaryMoney: 0.0,
        marchMoney: 0.0,
        aprilMoney: 0.0,
        mayMoney: 0.0,
        juneMoney: 0.0,
        julyMoney: 0.0,
        augustMoney: 0.0,
        septemberMoney: 0.0,
        octoberMoney: 0.0,
        novemberMoney: 0.0,
        decemberMoney: 0.0,
      },
      {
        type: "实际利润",
        deptname: "第四个板块",
        zjzmoney: 0.0,
        januaryMoney: -437.04,
        februaryMoney: 55.32,
        marchMoney: -1101.3,
        aprilMoney: 388.38,
        mayMoney: 2642.51,
        juneMoney: 607.41,
        julyMoney: -69.02,
        augustMoney: 4665.14,
        septemberMoney: 0.0,
        octoberMoney: 0.0,
        novemberMoney: 0.0,
        decemberMoney: 0.0,
      },
      {
        type: "预算利润",
        deptname: "第五个板块",
        zjzmoney: 0.0,
        januaryMoney: 0.0,
        februaryMoney: 0.0,
        marchMoney: 0.0,
        aprilMoney: 0.0,
        mayMoney: 0.0,
        juneMoney: 0.0,
        julyMoney: 0.0,
        augustMoney: 0.0,
        septemberMoney: 0.0,
        octoberMoney: 0.0,
        novemberMoney: 0.0,
        decemberMoney: 0.0,
      },
      {
        type: "实际利润",
        deptname: "第五个板块",
        zjzmoney: 0.0,
        januaryMoney: 2.78,
        februaryMoney: 20.53,
        marchMoney: 8.66,
        aprilMoney: 20.67,
        mayMoney: 435.14,
        juneMoney: 41.44,
        julyMoney: 15.71,
        augustMoney: 25.1,
        septemberMoney: 0.0,
        octoberMoney: 0.0,
        novemberMoney: 0.0,
        decemberMoney: 0.0,
      },
      {
        type: "预算利润",
        deptname: "第六个板块",
        zjzmoney: 0.0,
        januaryMoney: 0.0,
        februaryMoney: 0.0,
        marchMoney: 0.0,
        aprilMoney: 0.0,
        mayMoney: 0.0,
        juneMoney: 0.0,
        julyMoney: 0.0,
        augustMoney: 0.0,
        septemberMoney: 0.0,
        octoberMoney: 0.0,
        novemberMoney: 0.0,
        decemberMoney: 0.0,
      },
      {
        type: "实际利润",
        deptname: "第六个板块",
        zjzmoney: 0.0,
        januaryMoney: -34.27,
        februaryMoney: 3.46,
        marchMoney: -2924.74,
        aprilMoney: -193.37,
        mayMoney: 914.59,
        juneMoney: 803.58,
        julyMoney: -815.51,
        augustMoney: 84.1,
        septemberMoney: 0.0,
        octoberMoney: 0.0,
        novemberMoney: 0.0,
        decemberMoney: 0.0,
      },
      {
        type: "预算利润",
        deptname: "第七个板块",
        zjzmoney: 0.0,
        januaryMoney: 0.0,
        februaryMoney: 0.0,
        marchMoney: 0.0,
        aprilMoney: 0.0,
        mayMoney: 0.0,
        juneMoney: 0.0,
        julyMoney: 0.0,
        augustMoney: 0.0,
        septemberMoney: 0.0,
        octoberMoney: 0.0,
        novemberMoney: 0.0,
        decemberMoney: 0.0,
      },
      {
        type: "实际利润",
        deptname: "第七个板块",
        zjzmoney: 0.0,
        januaryMoney: -81.09,
        februaryMoney: -12.07,
        marchMoney: -2.45,
        aprilMoney: -99.94,
        mayMoney: 488.92,
        juneMoney: 209.04,
        julyMoney: 37.8,
        augustMoney: 342.53,
        septemberMoney: 0.0,
        octoberMoney: 0.0,
        novemberMoney: 0.0,
        decemberMoney: 0.0,
      },
      {
        type: "预算利润",
        deptname: "总公司",
        zjzmoney: 0.0,
        januaryMoney: 0.0,
        februaryMoney: 0.0,
        marchMoney: 0.0,
        aprilMoney: 0.0,
        mayMoney: 0.0,
        juneMoney: 0.0,
        julyMoney: 0.0,
        augustMoney: 0.0,
        septemberMoney: 0.0,
        octoberMoney: 0.0,
        novemberMoney: 0.0,
        decemberMoney: 0.0,
      },
      {
        type: "实际利润",
        deptname: "总公司",
        zjzmoney: 0.0,
        januaryMoney: 639.83,
        februaryMoney: 813.44,
        marchMoney: 780.8,
        aprilMoney: 97.56,
        mayMoney: 2.12,
        juneMoney: 1.58,
        julyMoney: 81.77,
        augustMoney: 89.62,
        septemberMoney: 0.0,
        octoberMoney: 0.0,
        novemberMoney: 0.0,
        decemberMoney: 0.0,
      },
    ];
    let liaaa = calculateTotals(TableList);
    liaaa.forEach((item) => {
      let a = [
        item.januaryMoney,
        item.februaryMoney,
        item.marchMoney,
        item.aprilMoney,
        item.mayMoney,
        item.juneMoney,
        item.julyMoney,
        item.augustMoney,
        item.septemberMoney,
        item.octoberMoney,
        item.novemberMoney,
        item.decemberMoney,
      ];
      item.HeJi = Fn_HeJi(a);
      item.noMoney = FN_NoMoney(item);
    });
    let oneListTwo = AREA_Fn(liaaa);
    oneListTwo.forEach((item) => {
      item.noMoney = FN_NoMoney(item);
    });
    queryParams.value.tableConfig.tableData.all = oneListTwo;
    console.log("测试测试", oneListTwo);
    antv_Demo(oneListTwo);
  }, 300);
};
// 计算每一行 1月到12月的总和
const Fn_HeJi = (item) => {
  let total = 0;
  for (let i = 0; i < item.length; i++) {
    total += Number(item[i]);
  }
  return total.toFixed(2);
};
// 根据 部门  把相同组的放到一起,并且在下边追加 余额对象
const AREA_Fn = (list) => {
  let aa = transformData(list, [
    "januaryMoney",
    "februaryMoney",
    "marchMoney",
    "aprilMoney",
    "mayMoney",
    "juneMoney",
    "julyMoney",
    "augustMoney",
    "septemberMoney",
    "octoberMoney",
    "novemberMoney",
    "decemberMoney",
    "HeJi",
  ]);

  let bb = AREA_Fn2(aa);
  return bb;
};
const transformData = (data, fieldsToSum) => {
  const groupedData = {};
  // 遍历输入数组,按 deptname 分组
  data.forEach((item) => {
    const { deptname, ...rest } = item; // 解构出 deptname 和剩余字段
    if (!groupedData[deptname]) {
      groupedData[deptname] = []; // 初始化部门数组
    }
    groupedData[deptname].push(rest); // 将剩余字段加入对应的部门数组
  });

  // 遍历每个部门,并在每个部门内添加 '差额' 对象
  const result = Object.entries(groupedData).map(([dept, items]) => {
    // 创建 '差额' 对象
    const differenceItem = { deptname: dept, type: "差额" };

    // 遍历第一个对象的键值,排除 deptname 和 type
    for (const key in items[0]) {
      if (key !== "deptname" && key !== "type" && key !== "zjzmoney") {
        // 排除 deptname 和 type 字段
        differenceItem[key] = 0; // 将值设为 0
        differenceItem.zjzmoney = items[0].zjzmoney;
      }
    }

    let ccc = [
      ...items.map((item) => ({ deptname: dept, ...item })),
      differenceItem,
    ];

    let dddd = calculateDifference(ccc, fieldsToSum);
    // 返回当前部门的对象数组,包括原始数据和新加的差额对象
    return dddd;
  });
  // 展平结果数组
  return result.flat();
};
function calculateDifference(list, keyList) {
  // 定义变量来保存实际利润和预算利润
  let selfRecruitCost = {}; // 存储实际利润
  let supplierCost = {}; // 存储预算利润
  // 遍历 list,分别提取实际利润和预算利润
  list.forEach((item) => {
    if (item.type === "实际利润") {
      keyList.forEach((key) => {
        selfRecruitCost[key] = item[key]; // 复制实际利润字段
      });
    } else if (item.type === "预算利润") {
      keyList.forEach((key) => {
        supplierCost[key] = item[key]; // 复制预算利润字段
      });
    }
  });
  // 找到差额项
  let differenceItem = list.find((item) => item.type === "差额");
  // 计算差额
  if (differenceItem) {
    keyList.forEach((key) => {
      let aa = (selfRecruitCost[key] || 0) - (supplierCost[key] || 0);
      differenceItem[key] = aa.toFixed(2);
    });
  }
  return list; // 返回更新后的 list
}

// 根据 部门  把相同组的放到一起,并且在下边追加 预算完成率对象
const AREA_Fn2 = (list) => {
  let aa = transformData2(list, [
    "januaryMoney",
    "februaryMoney",
    "marchMoney",
    "aprilMoney",
    "mayMoney",
    "juneMoney",
    "julyMoney",
    "augustMoney",
    "septemberMoney",
    "octoberMoney",
    "novemberMoney",
    "decemberMoney",
    "HeJi",
  ]);

  return aa;
};
const transformData2 = (data, fieldsToSum) => {
  const groupedData = {};
  // 遍历输入数组,按 deptname 分组
  data.forEach((item) => {
    const { deptname, ...rest } = item; // 解构出 deptname 和剩余字段
    if (!groupedData[deptname]) {
      groupedData[deptname] = []; // 初始化部门数组
    }
    groupedData[deptname].push(rest); // 将剩余字段加入对应的部门数组
  });

  // 遍历每个部门,并在每个部门内添加 '预算完成率' 对象
  const result = Object.entries(groupedData).map(([dept, items]) => {
    // 创建 '预算完成率' 对象
    const differenceItem = { deptname: dept, type: "预算完成率" };
    // 遍历第一个对象的键值,排除 deptname 和 type
    for (const key in items[0]) {
      if (key !== "deptname" && key !== "type" && key !== "zjzmoney") {
        // 排除 deptname 和 type 字段
        differenceItem[key] = 0; // 将值设为 0
        differenceItem.zjzmoney = items[0].zjzmoney;
      }
    }
    let ccc = [
      ...items.map((item) => ({ deptname: dept, ...item })),
      differenceItem,
    ];
    let dddd = calculateDifference2(ccc, fieldsToSum);
    // 返回当前部门的对象数组,包括原始数据和新加的预算完成率对象
    return dddd;
  });
  // console.log(result);
  // 展平结果数组
  return result.flat();
};
function calculateDifference2(list, keyList) {
  // 定义变量来保存实际利润和预算利润
  let selfRecruitCost = {}; // 存储实际利润
  let supplierCost = {}; // 存储预算利润
  // 遍历 list,分别提取实际利润和预算利润
  list.forEach((item) => {
    if (item.type === "实际利润") {
      keyList.forEach((key) => {
        selfRecruitCost[key] = item[key]; // 复制实际利润字段
      });
    } else if (item.type === "预算利润") {
      keyList.forEach((key) => {
        supplierCost[key] = item[key]; // 复制预算利润字段
      });
    }
  });
  // 找到预算完成率项
  let differenceItem = list.find((item) => item.type === "预算完成率");
  // 计算预算完成率
  if (differenceItem) {
    keyList.forEach((key) => {
      let a = selfRecruitCost[key] || 0;
      let b = supplierCost[key] || 0;
      if (a === 0 || b == 0) {
        differenceItem[key] = "0%";
      } else {
        let cc = (a / b) * 100;
        differenceItem[key] = `${cc.toFixed(0)}%`;
      }
    });
  }
  return list; // 返回更新后的 list
}
// 搜索
const searchData = () => {
  getPageList();
};
onMounted(() => {
  Look_Action.value = route.query.Type_Action_Look_Value;
  getPageList();
});
</script>

<style>
.jsxAAA_Did {
  text-align: center;
  display: flex;
  flex-direction: column;
}

.jsxBBB_Did {
  /* width: 100%; */
  background-color: #89f0d1;
  box-sizing: border-box;
  padding: 5px 10px;
  margin-bottom: 10px;
  border-bottom: 1px solid #dcdfe6;
}

.my-header-cellTwo {
  font-weight: bold !important;
  background: #f2f6fc !important;
  color: #303133;
}

.el-table__body tr:hover > td {
  background-color: #a7a8eb !important;
}
</style>
<style lang="less" scoped>
/deep/.el-scrollbar {
  .el-scrollbar__bar.is-horizontal {
    height: 14px;
  }

  .el-scrollbar__bar.is-vertical {
    width: 14px;
  }

  .el-scrollbar__bar.is-horizontal .el-scrollbar__thumb {
    opacity: 1;
    background-color: #7ef8ee;
    box-shadow: 0 0 6px #00000026;
  }

  .el-scrollbar__bar.is-vertical .el-scrollbar__thumb {
    opacity: 1;
    background-color: #7ef8ee;
    box-shadow: 0 0 6px #00000026;
  }
}

/deep/.el-drawer__body {
  padding: 0 !important;
}

.home {
  .page-main {
    height: 100vh;
    background-color: #ffffff;
  }

  .page-main .el-main {
    padding: 5px 10px 10px 10px;
  }

  .page-main .el-header {
    height: auto !important;
    padding: 5px 10px 0 10px;
  }

  .page-main .el-footer {
    padding: 10px;
    text-align: right;
  }

  .el-header .el-row {
    padding-top: 5px;
  }

  .el-header .query-params_hide {
    height: 0;
  }

  /*搜索条件每行对应 height 45px*/
  .el-header .query-params_show {
    min-height: 90px;
  }

  .el-header .el-dropdown__caret-button {
    height: 32px;
  }

  .form-edit .el-dialog__header {
    padding: 5px;
  }

  .form-edit .el-form-item__content,
  .form-edit .el-date-editor.el-input,
  .form-edit .el-select {
    width: 200px;
  }

  .form-edit .el-form-item label {
    font-weight: 500;
  }

  .form-edit .el-tabs__content {
    height: calc(100% - 40px);
    overflow: auto;
  }

  .form-edit .el-table__fixed-body-wrapper {
    top: 37px !important;
  }

  .form-edit .el-dialog__footer {
    padding-bottom: 10px;
  }

  .item-select .el-dialog__header {
    padding: 1px 20px;
    background-color: rgba(0, 0, 0, 0.1);
  }

  .item-select .el-dialog__body {
    padding: 0;
  }

  .cell .el-checkbox {
    margin: 0;
  }

  span[class="el-tooltip el-icon-setting"],
  span[class="el-tooltip el-icon-setting focusing"] {
    font-size: 25px;
    position: absolute;
    top: 0;
    bottom: 0;
    right: 10px;
    margin: auto;
    cursor: pointer;
    color: #409eff;
  }

  .el-table__fixed,
  .el-table__fixed-right {
    height: auto !important;
    bottom: 11px;
  }

  #orderTemp {
    height: 100%;
    width: 100%;
  }

  /*行颜色*/
  .el-table .cutoff-row {
    background: #ffd9b3;
  }

  .el-table .enabled-row {
    background: #f6dbdb;
  }

  .el-date-editor.el-input,
  .el-date-editor.el-input__inner {
    width: 100% !important;
  }

  a {
    color: #337ab7;
    text-decoration: none;
  }

  a:focus,
  a:hover {
    color: #23527c;
    text-decoration: underline;
  }

  .el-tabs__header {
    margin: 0 0 5px !important;
  }

  /deep/ .el-dialog__header {
    padding: 0;
  }

  .el-form-item--small {
    margin-bottom: 5px;
  }

  .my-header {
    display: flex;
    flex-direction: row;
    justify-content: space-between;
  }

  /deep/ .el-dialog__body {
    padding: 10px 10px;
  }

  /deep/ .el-upload-list {
    height: 200px;
    overflow-y: auto;
  }

  /deep/ .el-dialog__body {
    height: 90% !important;
  }

  /deep/.el-table .cell {
    padding: 0 2px;
  }

  /deep/.el-drawer__header {
    margin-bottom: 0;
    // padding-top: 0;
  }

  /* 左右摆动 */
  .shake-box {
    cursor: pointer;
    animation: shake 1.5s linear infinite;
  }

  @keyframes shake {
    10% {
      transform: rotate(15deg);
    }

    20% {
      transform: rotate(-10deg);
    }

    30% {
      transform: rotate(5deg);
    }

    40% {
      transform: rotate(-5deg);
    }

    50%,
    100% {
      transform: rotate(0deg);
    }
  }

  .problem {
    width: 100%;
    height: 100%;
    // background-color: #e48e8e;
    overflow-y: auto;
  }
}
</style>

新建一个名为 ThreeXiangQingLook.vue 的文件当做打印页面。

暂时不知道怎么把 图表数据导出excel,所以采取了一个笨方法:图表数组数据都有了,直接把这个放到一个table表格里,然后在通过 XLSX导出为excel文件。

<!-- 预算与实际---页面 -->
<template>
  <div class="home">
    <el-container class="page-main">
      <el-header height="auto">
        <el-button
          style="margin-left: 10px"
          type="success"
          size="small"
          @click="click_look"
          >当前页导出excel</el-button
        >
      </el-header>
      <el-main
        :style="{
          height: queryParams.toolQuery.queryParamsShow
            ? 'calc(100% - 200px)'
            : 'calc(100% - 180px)',
        }"
      >
        <el-table
          :data="queryParams.tableConfig.tableData.all"
          :element-loading-text="queryParams.loadingTxt"
          v-loading="queryParams.loading.table"
          highlight-current-row
          size="small"
          height="100%"
          ref="tableData"
          id="ThreeXiangQingTabLe"
          border
          :header-cell-class-name="my_header_cellTwo"
          :row-class-name="tableRowClassName"
          :span-method="objectSpanMethod"
        >
          <template
            v-for="(
              column, index
            ) in queryParams.tableConfig.tableColumn.filter(
              (item) => item.show
            )"
          >
            <el-table-column
              align="center"
              :label="column.label"
              :width="column.width"
              :prop="column.field"
              :fixed="column.fixed"
              :sortable="column.sortable ? true : false"
            >
            </el-table-column>
          </template>
        </el-table>
      </el-main>
    </el-container>
  </div>
</template>
<script setup>
import {
  ref,
  onMounted,
  nextTick,
} from "vue";
import {
  rowMergeHandle,
} from "../../../utile/tool";
import * as XLSX from "xlsx";
const tableData = ref(null);
let queryParams = ref({
  loading: {
    table: false,
  },
  tableConfig: {
    tableData: {
      all: [],
    },
    tableColumn: [
      {
        field: "deptname",
        show: true,
        label: "部门",
        width: "150",
        fixed: "left",
        sortable: false,
        overflowShow: false,
        disabled: true,
      },
      {
        field: "zjzmoney",
        show: true,
        label: "年度目标",
        width: "150",
        fixed: "left",
        sortable: false,
        overflowShow: false,
        disabled: true,
      },
      {
        field: "type",
        show: true,
        label: "类型",
        fixed: "left",
        width: "100",
        sortable: false,
        overflowShow: false,
        disabled: true,
      },
      {
        field: "januaryMoney",
        show: true,
        label: "1月",
        width: "200",
        sortable: false,
        overflowShow: false,
        disabled: true,
      },
      {
        field: "februaryMoney",
        show: true,
        label: "2月",
        width: "200",
        sortable: false,
        overflowShow: false,
        disabled: true,
      },
      {
        field: "marchMoney",
        show: true,
        label: "3月",
        width: "200",
        sortable: false,
        overflowShow: false,
        disabled: true,
      },
      {
        field: "aprilMoney",
        show: true,
        label: "4月",
        width: "200",
        sortable: false,
        overflowShow: false,
        disabled: true,
      },
      {
        field: "mayMoney",
        show: true,
        label: "5月",
        width: "200",
        sortable: false,
        overflowShow: false,
        disabled: true,
      },
      {
        field: "juneMoney",
        show: true,
        label: "6月",
        width: "200",
        sortable: false,
        overflowShow: false,
        disabled: true,
      },
      {
        field: "julyMoney",
        show: true,
        label: "7月",
        width: "200",
        sortable: false,
        overflowShow: false,
        disabled: true,
      },
      {
        field: "augustMoney",
        show: true,
        label: "8月",
        width: "200",
        sortable: false,
        overflowShow: false,
        disabled: true,
      },
      {
        field: "septemberMoney",
        show: true,
        label: "9月",
        width: "200",
        sortable: false,
        overflowShow: false,
        disabled: true,
      },
      {
        field: "octoberMoney",
        show: true,
        label: "10月",
        width: "200",
        sortable: false,
        overflowShow: false,
        disabled: true,
      },
      {
        field: "novemberMoney",
        show: true,
        label: "11月",
        width: "200",
        sortable: false,
        overflowShow: false,
        disabled: true,
      },
      {
        field: "decemberMoney",
        show: true,
        label: "12月",
        width: "200",
        sortable: false,
        overflowShow: false,
        disabled: true,
      },
      {
        field: "noMoney",
        show: true,
        label: "未完成年度目标额度",
        width: "130",
        fixed: "right",
        sortable: false,
        overflowShow: false,
        disabled: true,
      },
      {
        field: "HeJi",
        show: true,
        label: "全年合计",
        width: "130",
        fixed: "right",
        sortable: false,
        overflowShow: false,
        disabled: true,
      },
    ],

    tableColumnLook: [],
  },
  pageConfig: {
    //每页行数F_IsCutOff
    limit: 100,
    // 当前页
    page: 1,
    //总记录数
    count: 0,
  },

  needMergeArr: ["deptname", "zjzmoney"],
  rowMergeArrs: [],

  toolQuery: {
    queryParams: {
      sqksjs: null, //申请时间
      area: null, //部门
      actions: null,
      customername: null, //用工单位
      bug: "全部",
      type: "全部",
    },
    queryParamsShow: true,
  },
  direction: 1,
});

// 表头变色
const my_header_cellTwo = ({ column, rowIndex, columnIndex }) => {
  if (column.label == "年度目标") {
    return "BudgetStyle11";
  } else if (
    column.label == "1月" ||
    column.label == "2月" ||
    column.label == "3月" ||
    column.label == "4月" ||
    column.label == "5月" ||
    column.label == "6月" ||
    column.label == "7月" ||
    column.label == "8月" ||
    column.label == "9月" ||
    column.label == "10月" ||
    column.label == "11月" ||
    column.label == "12月"
  ) {
    return "BudgetStyle55";
  } else {
    return "BudgetStyle55";
  }
};
// 指定列变色
const columnbackgroundStyle = ({ row, column, rowIndex, columnIndex }) => {
  if (column.label == "年度目标") {
    return { "background-color": "#92d050", color: "#000" };
  }
};
const tableRowClassName = ({ row, rowIndex }) => {
  return "";
};

function convertStringNumbersToNumbers(arr) {
  arr.forEach((obj) => {
    // 遍历对象的每个属性
    for (let key in obj) {
      // 确保属性是对象自身的属性
      if (obj.hasOwnProperty(key)) {
        // 检查属性值是否为数字字符串
        if (!isNaN(obj[key]) && typeof obj[key] === "string") {
          obj[key] = Number(obj[key]); // 转换为数字
        }
      }
    }
  });
  return arr;
}

const props = defineProps({
  ArrayList: {
    type: Array,
    default: [],
  },
});

// 列表初始化
const getPageList = () => {
  queryParams.value.loading.table = true;
  queryParams.value.loadingTxt = "加载计算中。。。";

  queryParams.value.tableConfig.tableData.all = [];

  window.setTimeout(() => {
    console.log("传来的数据", props.ArrayList);

    queryParams.value.loading.table = false;
    queryParams.value.loadingTxt = "";


    queryParams.value.tableConfig.tableData.all = props.ArrayList;
    queryParams.value.rowMergeArrs = rowMergeHandle(
      queryParams.value.needMergeArr,
      props.ArrayList
    );
    nextTick(() => {
      if (tableData.value && tableData.value.doLayout) {
        tableData.value.doLayout();
      }
    });

    
  }, 1000);
};

// 单元格合并
const objectSpanMethod = ({ row, column, rowIndex, columnIndex }) => {
  for (let res in queryParams.value.needMergeArr) {
    if (queryParams.value.needMergeArr[res] == column.property) {
      return mergeAction(column.property, rowIndex, columnIndex);
    }
  }
};
const mergeAction = (val, rowIndex) => {
  let _row = queryParams.value.rowMergeArrs[val].rowArr[rowIndex];
  let _col = _row > 0 ? 1 : 0;
  return [_row, _col];
};

const click_look = () => {
  console.log("需要导出");
  exportToExcel("#ThreeXiangQingTabLe", queryParams.value.PageName);
};

function exportToExcel(idSelector, fileName, titleNum = 1) {
  const table = document.querySelector(idSelector).cloneNode(true);
  const fixedRightNode = table.querySelector(".el-table__fixed-right");
  if (fixedRightNode) {
    table.removeChild(fixedRightNode);
  }
  const fixedNode = table.querySelector(".el-table__fixed");
  if (fixedNode) {
    table.removeChild(fixedNode);
  }
  const headerDom = table.querySelector(".el-table__header-wrapper");
  const bodyDom = table.querySelector(".el-table__body-wrapper");
  // 找到操作列并删除它
  const actionColumnCells = Array.from(
    headerDom.querySelectorAll(".cell")
  ).filter((cell) => cell.innerText === "查看");
  actionColumnCells.forEach((cell) => {
    const index = parseInt(cell.cellIndex, 10);
    if (!isNaN(index)) {
      cell.parentElement.removeChild(cell);
      Array.from(
        bodyDom.querySelectorAll(`.cell:nth-child(${index + 1})`)
      ).forEach((cell) => cell.parentElement.removeChild(cell));
    }
  });
  const container = document.createElement("div");
  container.appendChild(headerDom);
  container.appendChild(bodyDom);
  const ws = XLSX.utils.table_to_sheet(container, {
    raw: true,
    display: true,
  });
  const wb = XLSX.utils.book_new();
  XLSX.utils.book_append_sheet(wb, ws, "Sheet1");
  const wbout = XLSX.write(wb, {
    bookType: "xlsx",
    bookSST: true,
    type: "array",
  });
  try {
    const fileData = new Blob([wbout], {
      type: "application/octet-stream",
    });
    const a = document.createElement("a");
    a.href = URL.createObjectURL(fileData);
    a.download = `${fileName}.xlsx`;
    a.click();
  } catch (e) {}
}

const jcsg = () => {
  getPageList();
};
onMounted(() => {
  jcsg();
});
</script>

<style>
.jsxAAA_Did {
  text-align: center;
  display: flex;
  flex-direction: column;
}
.jsxBBB_Did {
  /* width: 100%; */
  background-color: #89f0d1;
  box-sizing: border-box;
  padding: 5px 10px;
  margin-bottom: 10px;
  border-bottom: 1px solid #dcdfe6;
}

.my-header-cellTwo {
  font-weight: bold !important;
  background: #f2f6fc !important;
  color: #303133;
}

.el-table__body tr:hover > td {
  background-color: #a7a8eb !important;
}
</style>
<style lang="less" scoped>
/deep/.el-scrollbar {
  .el-scrollbar__bar.is-horizontal {
    height: 14px;
  }
  .el-scrollbar__bar.is-vertical {
    width: 14px;
  }
  .el-scrollbar__bar.is-horizontal .el-scrollbar__thumb {
    opacity: 1;
    background-color: #7ef8ee;
    box-shadow: 0 0 6px #00000026;
  }

  .el-scrollbar__bar.is-vertical .el-scrollbar__thumb {
    opacity: 1;
    background-color: #7ef8ee;
    box-shadow: 0 0 6px #00000026;
  }
}
/deep/.el-drawer__body {
  padding: 0 !important;
}
.home {
  .page-main {
    height: 100vh;
    background-color: #ffffff;
  }

  .page-main .el-main {
    padding: 5px 10px 10px 10px;
  }

  .page-main .el-header {
    height: auto !important;
    padding: 5px 10px 0 10px;
  }

  .page-main .el-footer {
    padding: 10px;
    text-align: right;
  }

  .el-header .el-row {
    padding-top: 5px;
  }

  .el-header .query-params_hide {
    height: 0;
  }

  /*搜索条件每行对应 height 45px*/
  .el-header .query-params_show {
    min-height: 90px;
  }

  .el-header .el-dropdown__caret-button {
    height: 32px;
  }

  .form-edit .el-dialog__header {
    padding: 5px;
  }

  .form-edit .el-form-item__content,
  .form-edit .el-date-editor.el-input,
  .form-edit .el-select {
    width: 200px;
  }

  .form-edit .el-form-item label {
    font-weight: 500;
  }

  .form-edit .el-tabs__content {
    height: calc(100% - 40px);
    overflow: auto;
  }

  .form-edit .el-table__fixed-body-wrapper {
    top: 37px !important;
  }

  .form-edit .el-dialog__footer {
    padding-bottom: 10px;
  }

  .item-select .el-dialog__header {
    padding: 1px 20px;
    background-color: rgba(0, 0, 0, 0.1);
  }

  .item-select .el-dialog__body {
    padding: 0;
  }

  .cell .el-checkbox {
    margin: 0;
  }

  span[class="el-tooltip el-icon-setting"],
  span[class="el-tooltip el-icon-setting focusing"] {
    font-size: 25px;
    position: absolute;
    top: 0;
    bottom: 0;
    right: 10px;
    margin: auto;
    cursor: pointer;
    color: #409eff;
  }

  .el-table__fixed,
  .el-table__fixed-right {
    height: auto !important;
    bottom: 11px;
  }

  #orderTemp {
    height: 100%;
    width: 100%;
  }

  /*行颜色*/
  .el-table .cutoff-row {
    background: #ffd9b3;
  }

  .el-table .enabled-row {
    background: #f6dbdb;
  }

  .el-date-editor.el-input,
  .el-date-editor.el-input__inner {
    width: 100% !important;
  }

  a {
    color: #337ab7;
    text-decoration: none;
  }

  a:focus,
  a:hover {
    color: #23527c;
    text-decoration: underline;
  }

  .el-tabs__header {
    margin: 0 0 5px !important;
  }

  /deep/ .el-dialog__header {
    padding: 0;
  }

  .el-form-item--small {
    margin-bottom: 5px;
  }

  .my-header {
    display: flex;
    flex-direction: row;
    justify-content: space-between;
  }

  /deep/ .el-dialog__body {
    padding: 10px 10px;
  }

  /deep/ .el-upload-list {
    height: 200px;
    overflow-y: auto;
  }

  /deep/ .el-dialog__body {
    height: 90% !important;
  }

  /deep/.el-table .cell {
    padding: 0 2px;
  }

  /deep/.el-drawer__header {
    margin-bottom: 0;
    // padding-top: 0;
  }

  /* 左右摆动 */
  .shake-box {
    cursor: pointer;
    animation: shake 1.5s linear infinite;
  }

  @keyframes shake {
    10% {
      transform: rotate(15deg);
    }

    20% {
      transform: rotate(-10deg);
    }

    30% {
      transform: rotate(5deg);
    }

    40% {
      transform: rotate(-5deg);
    }

    50%,
    100% {
      transform: rotate(0deg);
    }
  }

  .problem {
    width: 100%;
    height: 100%;
    // background-color: #e48e8e;
    overflow-y: auto;
  }
}
</style>

http://www.kler.cn/a/324803.html

相关文章:

  • ThinkPHP 模型如何更新数据
  • 通过地址获取LONG和LAT并且存入csv
  • 深度学习:transpose_qkv()与transpose_output()
  • 数据结构(初阶4)---循环队列详解
  • AtCoder Beginner Contest 380(A-F)
  • 谷歌AI进军教育,这将改变未来?
  • Golang | Leetcode Golang题解之第436题寻找右区间
  • 长文本溢出,中间位置显示省略号
  • 基于Node.js+Express+MySQL+VUE新闻网站管理系统的设计与实现
  • 小程序原生-地理定位功能介绍和实现
  • Service和Endpoints
  • 使用C#,MSSQL开发的钢结构加工系统
  • 如何在iPad上用Chrome实现无痕浏览
  • Acwing 快速幂
  • 力扣 简单 876.链表的中间结点
  • Leetcode面试经典150题-383.赎金信
  • 2024年【电工(高级)】考试题及电工(高级)考试内容
  • ISO 21434车辆网络安全风险评估的全面流程解析
  • 小柴冲刺软考中级嵌入式系统设计师系列二、嵌入式系统硬件基础知识(3)嵌入式系统的存储体系
  • 大模型落地需要一把“梯子”
  • 酒店智能开关的组成与功能
  • 【第十四周】PyTorch深度学习实践1
  • 浅说差分算法(上)
  • excel-VBA知识点记录
  • 服务器数据恢复—SAN环境下LUN映射出错导致文件系统一致性出错的数据恢复案例
  • 物联网系统中OLED屏主流驱动方案详解