123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493 |
- <template>
- <div class="w-full aa">
- <vxe-button class="float-right -top-20 mr-20 mb-4 z-50" @click="exportEvent"
- ><el-icon> <Download /> </el-icon> 导出</vxe-button
- >
- <vxe-grid
- v-if="$route.name != 'workerDrak'"
- v-bind="gridOptions"
- ref="gridRef"
- class="mt-10"
- :merge-cells="mergeCells"
- >
- <template #imgUrl_default="{ row }">
- <div>
- <div
- v-if="!row.ranking"
- class="text-center text-sm font-extrabold text-[#000000]"
- >
- 平均得分
- </div>
- <div v-if="row.ranking <= 3" class="text-center">
- <img class="mt-auto" :src="RANK_IMG[Number(row.ranking) - 1]" />
- </div>
- <div v-else-if="row.ranking" class="diamond">{{ row.ranking }}</div>
- </div>
- </template>
- <template #dim-allScore="{ row }">
- {{ row.allScore }}
- </template>
- </vxe-grid>
- <vxe-grid v-else v-bind="gridOptions" ref="gridRef1" class="mt-10">
- <template #imgUrl_default="{ row }">
- <div v-if="row.ranking <= 3" class="text-center">
- <img class="mt-auto" :src="RANK_IMG[Number(row.ranking) - 1]" />
- </div>
- <div v-else-if="row.ranking" class="diamond">{{ row.ranking }}</div>
- </template>
- <template #dim-allScore="{ row }">
- {{ row.allScore }}
- </template>
- </vxe-grid>
- </div>
- </template>
- <script setup>
- import { ElMessage } from "element-plus";
- import { ref, reactive, watch, onMounted, nextTick } from "vue";
- import rank1 from "@/assets/rank/rank1.png";
- import rank2 from "@/assets/rank/rank2.png";
- import rank3 from "@/assets/rank/rank3.png";
- import dayjs from "dayjs";
- import { useRoute } from "vue-router";
- const gridRef = ref(null);
- const gridRef1 = ref(null);
- // 导出数据
- const fileData = ref([]);
- const $route = useRoute();
- const RANK_IMG = [rank1, rank2, rank3];
- const deptName = ref("");
- const name = ref("");
- const mergeCells = ref([
- // 合并第一行前两列
- { row: 0, col: 0, rowspan: 1, colspan: 2 },
- { row: 2, col: 1, rowspan: 0, colspan: 0 }
- ]);
- const averageData = averageSore => {
- if (rawData.value.length > 0) {
- // let num = 0;
- // rawData.value.map(it => {
- // num = num + it.allScore;
- // });
- // num = num / rawData.value.length;
- rawData.value.unshift({
- dimensionList: [],
- allScore: rawData.value[0].averageSore,
- isAverageRow: true // 标记为平均分行
- });
- }
- };
- const selectYear = ref("2024-01-01");
- const gridOptions = reactive({
- border: true,
- loading: false,
- height: 500,
- sortConfig: {
- multiple: false
- },
- exportConfig: {},
- columns: [],
- data: [],
- showOverflow: true,
- showHeaderOverflow: true,
- showFooterOverflow: true,
- columnConfig: {
- resizable: true
- },
- scrollX: {
- enabled: true,
- gt: 0
- }
- });
- const tabTitle = ref();
- // 模拟接口数据
- const rawData = ref([]);
- const init = (item, deptNames, names) => {
- rawData.value = item;
- deptName.value = deptNames;
- name.value = names;
- if ($route.name != "workerDrak") {
- averageData(item.averageSore);
- }
- if (
- $route.name == "healthDrank" ||
- $route.name == "healthRank" ||
- $route.name == "healthDataDetail"
- ) {
- tabTitle.value = "医疗组";
- } else {
- tabTitle.value = "科室";
- }
- // 初始化
- createColumns();
- loadData();
- };
- defineExpose({
- init
- });
- // 判断key值是否相同返回具体值
- function getValueByKey(obj, key) {
- if (key in obj) {
- return obj[key];
- }
- return null; // 如果 key 不存在则返回 null
- }
- // 生成动态表头
- const createColumns = () => {
- let columns = [];
- console.log($route.name, "nnnnnn");
- if (
- $route.name == "workerDataDetail" ||
- $route.name === "headDataDetail" ||
- $route.name === "headDrank"
- ) {
- columns = [
- {
- title: "排名",
- field: "ranking",
- width: 70,
- slots: { default: "imgUrl_default" },
- fixed: "left" // 将此列固定在左侧
- },
- {
- title: "姓名",
- field: "assessmentObjectName",
- width: 100,
- fixed: "left" // 将此列固定在左侧
- },
- {
- title: "部门",
- field: "deptName",
- width: 150,
- fixed: "left" // 将此列固定在左侧
- },
- {
- title: "总得分",
- field: "allScore",
- sortable: true,
- width: 150,
- fixed: "right", // 将此列固定在右侧
- slots: { default: "dim-allScore" },
- sortBy({ column, row }) {
- // 如果是平均行(isAverageRow为true),则返回一个很大的值,避免被排序
- if (column.field in row && typeof row[column.field] === "number") {
- if (column.order == "asc") {
- if (row.isAverageRow) {
- return -9999999999;
- }
- } else {
- if (row.isAverageRow) {
- return 99999999999;
- }
- }
- } else {
- return -9999999999;
- }
- return row.allScore; // 返回正常的得分,进行排序
- }
- }
- ];
- } else {
- columns = [
- {
- title: "排名",
- field: "ranking",
- width: 70,
- slots: { default: "imgUrl_default" },
- fixed: "left" // 将此列固定在左侧
- },
- {
- title: tabTitle.value,
- field: "assessmentObjectName",
- width: 100,
- fixed: "left" // 将此列固定在左侧
- },
- {
- title: "总得分",
- field: "allScore",
- width: 150,
- sortable: true,
- fixed: "right", // 将此列固定在右侧
- slots: { default: "dim-allScore" },
- sortBy({ column, row }) {
- // 如果是平均行(isAverageRow为true),则返回一个很大的值,避免被排序
- if (column.field in row && typeof row[column.field] === "number") {
- if (column.order == "asc") {
- if (row.isAverageRow) {
- return -9999999999;
- }
- } else {
- if (row.isAverageRow) {
- return 99999999999;
- }
- }
- } else {
- return -9999999999;
- }
- return row.allScore; // 返回正常的得分,进行排序
- }
- }
- ];
- }
- const headerMap = new Map();
- // 遍历数据生成表头结构
- rawData.value.forEach(item => {
- item.dimensionList.forEach(dim => {
- if (!headerMap.has(dim.dimName)) {
- // 存储维度相关信息,包括 totalSore 和 dimWeight
- headerMap.set(dim.dimName, {
- dimWeight: dim.dimWeight || "0", // 默认值为 "-"
- totalSore: dim.totalSore || "0", // 默认值为 "-"
- quotas: [] // 用于存储 quota 列表
- });
- }
- dim.quotaList.forEach(quota => {
- const dimData = headerMap.get(dim.dimName);
- if (!dimData.quotas.some(q => q.quotaName === quota.quotaName)) {
- dimData.quotas.push({
- quotaName: quota.quotaName,
- quotaWeight: quota.quotaWeight || "0" // 默认值为 "-"
- });
- }
- });
- });
- });
- // 构建多级表头
- headerMap.forEach((dimData, dimName) => {
- const children = dimData.quotas.map(quota => ({
- title: `${quota.quotaName} ${quota.quotaWeight != "null" && quota.quotaWeight != "0" ? `(${quota.quotaWeight}%)` : ""}`, // 在 title 后拼接 quotaWeight
- width: 120,
- sortable: true,
- field: `${dimName}_${quota.quotaName}`, // 确保字段唯一
- sortBy({ column, row }) {
- // 如果是平均行(isAverageRow为true),则返回一个很大的值,避免被排序
- let aa = Number(row[column.field]);
- if (typeof aa === "number" && !isNaN(aa)) {
- if (column.order == "asc") {
- if (row.isAverageRow) {
- return -9999999999;
- }
- } else {
- if (row.isAverageRow) {
- return 99999999999;
- }
- }
- } else {
- // 倒序在最后
- if (column.order == "asc") {
- if (!row.isAverageRow) {
- return 9999999999999;
- } else {
- return -999999999999;
- }
- } else {
- if (!row.isAverageRow) {
- return -999999999999;
- } else {
- return 999999999999;
- }
- }
- }
- return getValueByKey(row, column.field); // 返回正常的得分,进行排序
- }
- }));
- // 添加维度名称及其对应的子列
- columns.push({
- title: `${dimName} ${dimData.dimWeight != "null" && dimData.dimWeight != "0" ? `(${dimData.dimWeight}%)` : ""}`, // 在 title 后拼接 dimWeight
- children
- });
- // 添加该维度的总分列
- columns.push({
- title: `总分`, // 可根据需要调整标题
- field: `${dimName}_totalSore`,
- width: 120,
- sortable: true,
- sortBy({ column, row }) {
- // 如果是平均行(isAverageRow为true),则返回一个很大的值,避免被排序
- let aa = Number(row[column.field]);
- if (typeof aa === "number" && !isNaN(aa)) {
- if (column.order == "asc") {
- if (row.isAverageRow) {
- return -9999999999;
- }
- } else {
- if (row.isAverageRow) {
- return 99999999999;
- }
- }
- } else {
- // 倒序在最后
- if (column.order == "asc") {
- if (!row.isAverageRow) {
- return 9999999999999;
- } else {
- return -999999999999;
- }
- } else {
- if (!row.isAverageRow) {
- return -999999999999;
- } else {
- return 999999999999;
- }
- }
- }
- return getValueByKey(row, column.field); // 返回正常的得分,进行排序
- }
- });
- });
- gridOptions.columns = columns;
- };
- // 加载数据
- // 保存原始数据副本
- const originalData = ref([]);
- const loadData = () => {
- gridOptions.loading = true;
- const tableData = rawData.value.map(item => {
- const row = {
- assessmentObjectName: item.assessmentObjectName,
- deptName: item.deptName,
- ranking: item.ranking,
- allScore: item.allScore,
- isAverageRow: item.isAverageRow || false // 确保数据里标记了是否为平均分行
- };
- item.dimensionList.forEach(dim => {
- let totalScore = 0;
- // 填充指标得分
- dim.quotaList.forEach(quota => {
- const fieldName = `${dim.dimName}_${quota.quotaName}`;
- row[fieldName] = quota.quotaScore;
- totalScore += quota.quotaScore;
- });
- // 填充维度总分
- const totalFieldName = `${dim.dimName}_totalSore`;
- row[totalFieldName] = dim.totalSore || totalScore;
- });
- return row;
- });
- originalData.value = [...tableData]; // 保存原始数据
- tableData[0].sortable = true;
- gridOptions.data = tableData;
- fileData.value = JSON.parse(JSON.stringify(tableData));
- if ($route.name != "workerDrak") {
- fileData.value[0].ranking = "平均得分";
- }
- // 使用 nextTick 确保表格渲染完成后再合并单元格
- nextTick(() => {
- if (gridRef.value) {
- gridRef.value.setMergeCells([
- { row: 0, col: 0, rowspan: 1, colspan: 2 },
- { row: 2, col: 1, rowspan: 0, colspan: 0 }
- ]);
- }
- });
- gridOptions.loading = false;
- };
- // 监听年份变化,重新渲染
- watch(selectYear, () => {
- // init(newVal.data, newVal.dept, newVal.name);
- createColumns();
- loadData();
- gridRef.value.setMergeCells([
- // 合并第一行前两列
- { row: 0, col: 0, rowspan: 1, colspan: 2 },
- { row: 2, col: 1, rowspan: 0, colspan: 0 }
- ]);
- });
- const setGridHeight = () => {
- // 设置表格的高度为设备的高度(例如,减去其他UI元素的高度)
- const height = window.innerHeight - 200; // 100 为你需要的偏移量(例如页头的高度)
- gridOptions.height = height;
- };
- onMounted(() => {
- setGridHeight();
- // 监听窗口大小变化,动态调整表格高度
- window.addEventListener("resize", setGridHeight);
- });
- // 导出
- const exportEvent = () => {
- let $grid;
- let fileName =
- localStorage.getItem("fileName") + dayjs().format("YYYY-MM-DD HH:mm:ss");
- if ($route.name != "workerDrak") {
- $grid = gridRef.value;
- } else {
- $grid = gridRef1.value;
- }
- if ($grid) {
- // gridOptions.exportConfig = {
- // type: "xlsx",
- // fileName: name
- // };
- $grid.exportData({
- type: "xlsx",
- filename: fileName,
- useStyle: true,
- isMerge: true,
- data: fileData.value
- });
- // $grid.exportData({
- // type: "xlsx",
- // fileName: name
- // });
- } else {
- ElMessage({
- message: "暂无数据",
- type: "warning"
- });
- }
- };
- </script>
- <style lang="scss" scoped>
- .diamond {
- display: flex;
- align-items: center;
- justify-content: center;
- width: 25px;
- /* 菱形宽度 */
- height: 25px;
- /* 菱形高度 */
- padding-top: 1px;
- margin: auto;
- clip-path: polygon(50% 0%, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%);
- /* 定义六边形的形状 */
- font-size: 12px;
- color: white;
- background-color: #d3e8f0;
- /* 背景颜色 */
- }
- .mytTable ::v-deep .el-table th.el-table__cell,
- ::v-deep .el-table th,
- ::v-deep .el-table tr {
- color: white;
- background-color: transparent !important;
- }
- .aaaa {
- background-color: black !important;
- }
- .aa {
- position: relative;
- }
- </style>
|