You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
56 lines
1.4 KiB
TypeScript
56 lines
1.4 KiB
TypeScript
|
1 month ago
|
export interface CSVColumn {
|
||
|
|
key: string
|
||
|
|
label: string
|
||
|
|
}
|
||
|
|
|
||
|
|
export const useCSVExport = () => {
|
||
|
|
const exportToCSV = (
|
||
|
|
data: Record<string, any>[],
|
||
|
|
columns: CSVColumn[],
|
||
|
|
filename: string = 'export.csv'
|
||
|
|
) => {
|
||
|
|
// 创建 CSV 头部
|
||
|
|
const headers = columns.map(col => `"${col.label}"`).join(',')
|
||
|
|
|
||
|
|
// 创建 CSV 数据行
|
||
|
|
const rows = data.map(row => {
|
||
|
|
return columns.map(col => {
|
||
|
|
const value = row[col.key]
|
||
|
|
// 处理特殊字符
|
||
|
|
if (typeof value === 'string') {
|
||
|
|
return `"${value.replace(/"/g, '""')}"`
|
||
|
|
}
|
||
|
|
return value
|
||
|
|
}).join(',')
|
||
|
|
})
|
||
|
|
|
||
|
|
// 组合完整的 CSV 内容
|
||
|
|
const csvContent = [
|
||
|
|
headers,
|
||
|
|
...rows
|
||
|
|
].join('\n')
|
||
|
|
|
||
|
|
// 添加 BOM 以支持中文
|
||
|
|
const BOM = '\uFEFF'
|
||
|
|
|
||
|
|
// 创建并下载文件
|
||
|
|
const blob = new Blob([BOM + csvContent], {
|
||
|
|
type: 'text/csv;charset=utf-8;'
|
||
|
|
})
|
||
|
|
|
||
|
|
const link = document.createElement('a')
|
||
|
|
const url = URL.createObjectURL(blob)
|
||
|
|
|
||
|
|
link.setAttribute('href', url)
|
||
|
|
link.setAttribute('download', filename)
|
||
|
|
link.style.visibility = 'hidden'
|
||
|
|
|
||
|
|
document.body.appendChild(link)
|
||
|
|
link.click()
|
||
|
|
document.body.removeChild(link)
|
||
|
|
}
|
||
|
|
|
||
|
|
return {
|
||
|
|
exportToCSV
|
||
|
|
}
|
||
|
|
}
|