/* * @Author: fxs bjnsfxs@163.com * @Date: 2024-08-20 17:15:49 * @LastEditors: fxs bjnsfxs@163.com * @LastEditTime: 2024-12-07 * @Description: * */ import type { ResponseInfo } from '@/types/res' import type { TableFieldInfo, TablePaginationSetting } from '@/types/table' import { initLoadResource } from '@/utils/resource' import { reactive, toRaw } from 'vue' // import { downLoadData } from '@/utils/table/table' import { generateRandomFileName } from '@/utils/common' import * as xlsx from 'xlsx' import axiosInstance from '../utils/axios/axiosInstance' import type { ReqConfig } from '@/types/dataAnalysis' // 资源的加载路径 const resourceInfo: Record = { defaultHead: `/img/default/defaultHead.png` } // 使用blob的资源路径信息 const blobUrlInfo = reactive>({}) // 初始化资源 initLoadResource(resourceInfo).then((data) => { Object.assign(blobUrlInfo, data) }) export function useTable( tableData: Array, paginationSetting: TablePaginationSetting, tableFieldsInfo: TableFieldInfo[] ) { /** * @description: 设置默认头像 * @param data 请求回来的数据表格 * @return 返回处理后的数据 */ const setDefaultHead = (data: Array): Array => { if (data) { data.map(async (item: any) => { if (!item.head) item.head = blobUrlInfo.defaultHead }) } return data } /** * 将请求的数据写入tableData * * 对开启分页的数据做单独的处理 * * @param dataList 数据列表 * @param total 数据总量 * @param openPagination 是否开启了分页查询 * @param openRemoteReq 是否是远程请求 * @return 成功返回true,反之false */ const setTableData = ( dataList: Array, total: number, openPagination: boolean, openRemoteReq: boolean ): boolean => { try { if (!dataList || dataList.length === 0) { tableData.length = 0 paginationSetting.total = 0 } else { // 确保返回的数据中有total才赋值,否则直接使用长度 if (total) { paginationSetting.total = total } else { paginationSetting.total = dataList.length } console.log(paginationSetting.total) // 处理有头像的字段 dataList = setDefaultHead(dataList) // 如果开启了分页,设置 tableData 为二维数组,否则为一维数组 const pageIndex = paginationSetting.currentPage ?? 0 if (openPagination && openRemoteReq) { tableData[pageIndex] = dataList } else { tableData.splice(0, tableData.length, ...dataList) } } return true } catch (err) { console.error('数据处理错误:', err) return false } } /** * @description 获取表格数据 * @param url 请求地址 * @param option 请求参数 * @return [表格数据,总数] */ const getTableData = async ( url: string, option: Record ): Promise<[Array, number]> => { try { const result = await axiosInstance.post(url, option) return [result.data ?? [], result.count ?? 0] } catch (err) { console.error('请求数据错误:', err) return [[], 0] } } /** * 开启行号功能后,计算行号 * @param index 当前行索引 */ const computedRowIndex = (index: number) => { return (paginationSetting.currentPage - 1) * paginationSetting.limit + index + 1 } /** * @description: 改变页码 * @param val */ const handleCurrentChange = (val: number) => { paginationSetting.currentPage = val } /** * @description 改变每页大小 * @param val */ const handleSizeChange = (val: number) => { paginationSetting.limit = val } /** * 插入均值行 * * @param needAverage 是否需要计算平均值 * @param openRemoteReqData 是否是远程请求 */ const insertAverageRow = (needAverage: boolean, openRemoteReqData: boolean) => { if (needAverage) { const rowData: any = {} const oldList: Array = JSON.parse(JSON.stringify(tableData)) Object.values(tableFieldsInfo).map((item: TableFieldInfo, index: number) => { const sum = oldList .map((item) => item.count) .reduce((accumulator, currentValue) => accumulator + currentValue, 0) const averageList = oldList .map((val) => val[item.name]) .filter((item) => item !== undefined) if (index === 0) rowData[item.name] = '均值' else if (item.name === 'count') rowData[item.name] = sum else { const num = averageList.reduce((accumulator, currentValue) => accumulator + currentValue, 0) / averageList.length rowData[item.name] = isNaN(num) ? 0 : num.toFixed(2) } }) if (openRemoteReqData) { tableData[0].splice(0, 0, rowData) } else { tableData.splice(0, 0, rowData) } } } /** * 清空表格数据 */ const resetTableData = () => { tableData.splice(0, tableData.length) } /** * @description: 根据计算出来的值去返回对应的颜色深度 * @param number 输入值 */ const getDecimalFromRange = (number: number) => { if (!number) return 0 if (number < 25) return 0.25 else if (number < 50) return 0.5 else if (number < 75) return 0.75 else return 1.0 // 如果number >= 75,则直接返回1.00 } /** * @description: 初始化分页配置,把传入的配置拷贝一份 */ const initPageConfig = (propPageConfig?: TablePaginationSetting) => { if (propPageConfig) { Object.assign(paginationSetting, JSON.parse(JSON.stringify(propPageConfig))) } } /** * @description: 初始化请求配置,用于把拷贝一份新的数据 */ const initReqConfig = (reqConfig: ReqConfig, propReqConfig?: ReqConfig) => { if (propReqConfig) { Object.assign(reqConfig, propReqConfig) } } /** * @description: 创建row-key优化表格性能 */ const createRowKey = () => { return `${Date.now()}-${Math.random().toString(36).slice(2, 11)}` } /** * @description: 下载表格数据 */ const downLoadTable = (headerMap: Record = {}) => { // downLoadData(generateRandomFileName(), JSON.parse(JSON.stringify(tableData))) const exportData = tableData .slice(1) .flat() .map((item) => { const rawData = toRaw(item) // 遍历对象的键,删除不在 validKeys 中的键 Object.keys(item).forEach((key) => { if (!(key in headerMap)) { delete item[key] } }) return rawData }) // 表头设置 // exportData.unshift(headerZh) const header = Object.keys(headerMap) const newData = [ { actionId: '事件ID', actionName: '事件名称', actionCount: '操作次数', actionUserCount: '操作用户数', activeUserRate: '活跃设备发生率', loginActiveRate: '每次启动发生数' }, ...exportData ] const workbook = xlsx.utils.book_new() const worksheet = xlsx.utils.json_to_sheet(newData, { header: header, skipHeader: true }) xlsx.utils.book_append_sheet(workbook, worksheet, 'Sheet1') return xlsx.writeFile(workbook, generateRandomFileName() + '.xlsx') } return { getTableData, setTableData, resetTableData, initPageConfig, initReqConfig, getDecimalFromRange, computedRowIndex, handleCurrentChange, handleSizeChange, insertAverageRow, createRowKey, downLoadTable } }