This commit is contained in:
Teo
2025-09-04 11:06:45 +08:00
parent 9d1f96309f
commit 910b24019e
83 changed files with 8390 additions and 834 deletions

View File

@ -0,0 +1,146 @@
// 封装exceljs
import ExcelJS from 'exceljs';
import FileSaver from 'file-saver';
/**
* 导出数据到Excel方法
* @param {Array[Object]} config.data 表格数据
* @param {Array[String]} config.fields 字段列表
* @param {Array[String]} config.headers excel表头列表[[]],可以是多级表头[['A1''B1'],['A2''B2']]
* @param {Array[Object]} config.merges 需要合并的单元格,需要考虑表头的行数[{row:1, col:1, rowspan: 1, colspan: 2}]
* @param {Array[Object]} config.attrs 单元格样式配置
* @param {Array[Object]} config.views 工作表视图配置
* @param {Array[Number]} config.columnsWidth 每个字段列对应的宽度
* @param {Object} config.protect 工作表保护【此配置会保护全表,一般推荐只针对单元格进行保护配置】
* @param {String} config.sheetName 工作表名称默认从sheet1开始
* @param {String} fileName excel文件名称
*/
export function exportDataToExcel(config, fileName) {
if (!config) return;
const options = {
fileName: fileName || `导出excel文件【${Date.now()}】.xlsx`,
worksheets: [],
};
if (!Array.isArray(config)) {
config = [config];
}
config.forEach((item) => {
// 深拷贝data【JSON.stringify有缺陷可自行换成_.cloneDeep】
const data = JSON.parse(JSON.stringify(item.data));
const results = data.map((obj) => {
return item.fields.map((key) => {
return obj[key];
});
});
// 生成完整excel数据
let excelData = [];
excelData = excelData.concat(item.headers).concat(results);
// 单元格合并处理【excel数据的第一行/列是从1开始】
let excelMerges = [];
excelMerges = item.merges.map((m) => {
return [m.row + 1, m.col + 1, m.row + m.rowspan, m.col + m.colspan];
});
// 单元格配置处理【excel数据的第一行/列是从1开始】
let excelAttrs = [];
excelAttrs = item.attrs.map((attr) => {
attr.rowStart += 1;
attr.rowEnd += 1;
attr.colStart += 1;
attr.colEnd += 1;
return attr;
});
options.worksheets.push({
data: excelData,
merges: excelMerges,
attrs: excelAttrs,
views: item.views,
columnsWidth: item.columnsWidth,
protect: item.protect,
sheetName: item.sheetName,
});
});
createExcel(options);
}
// 创建Excel文件方法
async function createExcel(options) {
if (!options.worksheets.length) return;
// 创建工作簿
const workbook = new ExcelJS.Workbook();
for (let i = 0; i < options.worksheets.length; i++) {
const sheetOption = options.worksheets[i];
// 创建工作表
const sheet = workbook.addWorksheet(sheetOption.sheetName || 'sheet' + (i + 1));
// 添加数据行
sheet.addRows(sheetOption.data);
// 配置视图
sheet.views = sheetOption.views;
// 单元格合并处理【开始行,开始列,结束行,结束列】
if (sheetOption.merges) {
sheetOption.merges.forEach((item) => {
sheet.mergeCells(item);
});
}
// 工作表保护
if (sheetOption.protect) {
const res = await sheet.protect(sheetOption.protect.password, sheetOption.protect.options);
}
// 单元格样式处理
if (sheetOption.attrs.length) {
sheetOption.attrs.forEach((item) => {
const attr = item.attr || {};
// 获取开始行-结束行; 开始列-结束列
const rowStart = item.rowStart;
const rowEnd = item.rowEnd;
const colStart = item.colStart;
const colEnd = item.colEnd;
if (rowStart) {
// 设置行
for (let r = rowStart; r <= rowEnd; r++) {
// 获取当前行
const row = sheet.getRow(r);
if (colStart) {
// 列设置
for (let c = colStart; c <= colEnd; c++) {
// 获取当前单元格
const cell = row.getCell(c);
Object.keys(attr).forEach((key) => {
// 给当前单元格设置定义的样式
cell[key] = attr[key];
});
}
} else {
// 未设置列,整行设置【大纲级别】
Object.keys(attr).forEach((key) => {
row[key] = attr[key];
});
}
}
} else if (colStart) {
// 未设置行,只设置了列
for (let c = colStart; c <= colEnd; c++) {
// 获取当前列,整列设置【大纲级别】
const column = sheet.getColumn(c);
Object.keys(attr).forEach((key) => {
column[key] = attr[key];
});
}
} else {
// 没有设置具体的行列,则为整表设置
Object.keys(attr).forEach((key) => {
sheet[key] = attr[key];
});
}
});
}
// 列宽设置
if (sheetOption.columnsWidth) {
for (let i = 0; i < sheet.columns.length; i++) {
sheet.columns[i].width = sheetOption.columnsWidth[i];
}
}
}
// 生成excel文件
workbook.xlsx.writeBuffer().then((buffer) => {
// application/octet-stream 二进制数据
FileSaver.saveAs(new Blob([buffer], { type: 'application/octet-stream' }), options.fileName);
});
}

View File

@ -9,13 +9,13 @@ export const getProjectTeam = async () => {
if (!isPermission && useUserStore().permissions[0] != '*:*:*') return;
const { id } = $cache.local.getJSON('selectedProject');
const { goId } = $cache.local.getJSON('selectedProject');
const res = await listProjectTeam({
pageNum: 1,
pageSize: 20,
orderByColumn: 'createTime',
isAsc: 'desc',
projectId: id
projectId: goId
});
const list = res.data.list.map((projectTeam: ProjectTeamVO) => ({

View File

@ -23,12 +23,13 @@ const requestGo: RequestGo = (config: any) => {
});
};
requestGo.download = function (url: string, params: any, filename: string) {
requestGo.download = function (url: string, params: any, filename: string, method: 'post' | 'get' = 'post') {
return request({
url,
method: 'post',
method: method,
baseURL: BASE_GO_URL,
data: params,
data: method === 'post' ? params : undefined,
params: method === 'get' ? params : undefined,
headers: {
'Authorization': `Bearer ${$cache.local.get('goToken') || ''}`
},

50
src/utils/sign.js Normal file
View File

@ -0,0 +1,50 @@
import crypto from 'crypto-js';
let coyr = 'coyrOrtiehanhan1223202409111457';
// 生成 nonce随机生成一个16位的字符串
function generateNonce() {
const chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
let nonce = '';
for (let i = 0; i < 16; i++) {
nonce += chars.charAt(Math.floor(Math.random() * chars.length));
}
return nonce;
}
// 生成当前时间戳(格式为 yyyyMMddHHmmss
function generateTimestamp() {
return new Date().getTime();
}
// 生成 MD5 哈希(需要引入第三方库,如 crypto-js
function md5Hash(str) {
return crypto.MD5(str).toString();
}
// 生成 SHA-256 哈希(需要引入第三方库,如 crypto-js
function sha256Hash(str) {
return crypto.SHA256(str).toString();
}
// 生成签名
function generateSignature(params, timestamp, nonce) {
// 加密
let coyr1 = md5Hash(coyr);
// 拼接时间戳、nonce 和 secretKey
let signStr = coyr1 + timestamp + nonce;
// MD5 加密
const md5Str = md5Hash(signStr);
// SHA-256 加密
let aaaa = sha256Hash(md5Str);
return aaaa;
}
function sign(data) {
// 生成签名
const timestamp = generateTimestamp();
const nonce = generateNonce();
const sign = generateSignature(data, timestamp, nonce);
return {
timestamp,
nonce,
sign,
};
}
// 封装
export default sign;

59
src/utils/storage.ts Normal file
View File

@ -0,0 +1,59 @@
import Cookies from 'js-cookie';
/**
* window.localStorage 浏览器永久缓存
* @method set 设置永久缓存
* @method get 获取永久缓存
* @method remove 移除永久缓存
* @method clear 移除全部永久缓存
*/
export const Local = {
// 设置永久缓存
set(key: string, val: any) {
window.localStorage.setItem(key, JSON.stringify(val));
},
// 获取永久缓存
get(key: string) {
let json: any = window.localStorage.getItem(key);
return JSON.parse(json);
},
// 移除永久缓存
remove(key: string) {
window.localStorage.removeItem(key);
},
// 移除全部永久缓存
clear() {
window.localStorage.clear();
},
};
/**
* window.sessionStorage 浏览器临时缓存
* @method set 设置临时缓存
* @method get 获取临时缓存
* @method remove 移除临时缓存
* @method clear 移除全部临时缓存
*/
export const Session = {
// 设置临时缓存
set(key: string, val: any) {
if (key === 'token') return Cookies.set(key, val);
window.sessionStorage.setItem(key, JSON.stringify(val));
},
// 获取临时缓存
get(key: string) {
if (key === 'token') return Cookies.get(key);
let json: any = window.sessionStorage.getItem(key);
return JSON.parse(json);
},
// 移除临时缓存
remove(key: string) {
if (key === 'token') return Cookies.remove(key);
window.sessionStorage.removeItem(key);
},
// 移除全部临时缓存
clear() {
Cookies.remove('token');
window.sessionStorage.clear();
},
};