148 lines
4.4 KiB
JavaScript
148 lines
4.4 KiB
JavaScript
// 链接管理工具函数
|
||
|
||
// 格式化链接状态
|
||
export function formatLinkStatus(status) {
|
||
const statusMap = {
|
||
'ACTIVE': '启用',
|
||
'INACTIVE': '禁用',
|
||
'EXPIRED': '已过期'
|
||
}
|
||
return statusMap[status] || status
|
||
}
|
||
|
||
// 获取链接状态标签类型
|
||
export function getLinkStatusType(status) {
|
||
const typeMap = {
|
||
'ACTIVE': 'success',
|
||
'INACTIVE': 'danger',
|
||
'EXPIRED': 'warning'
|
||
}
|
||
return typeMap[status] || 'info'
|
||
}
|
||
|
||
// 检查链接是否过期
|
||
export function isLinkExpired(expiredAt) {
|
||
if (!expiredAt) return false
|
||
return new Date(expiredAt) < new Date()
|
||
}
|
||
|
||
// 计算剩余时间
|
||
export function getRemainingTime(expiredAt) {
|
||
if (!expiredAt) return null
|
||
|
||
const now = new Date()
|
||
const expired = new Date(expiredAt)
|
||
const diff = expired - now
|
||
|
||
if (diff <= 0) return '已过期'
|
||
|
||
const days = Math.floor(diff / (1000 * 60 * 60 * 24))
|
||
const hours = Math.floor((diff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60))
|
||
const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60))
|
||
|
||
if (days > 0) return `${days}天${hours}小时`
|
||
if (hours > 0) return `${hours}小时${minutes}分钟`
|
||
return `${minutes}分钟`
|
||
}
|
||
|
||
// 生成二维码URL(使用在线服务)
|
||
export function generateQRCodeUrl(data, size = 200) {
|
||
return `https://api.qrserver.com/v1/create-qr-code/?size=${size}x${size}&data=${encodeURIComponent(data)}`
|
||
}
|
||
|
||
// 下载图片
|
||
export function downloadImage(url, filename) {
|
||
const link = document.createElement('a')
|
||
link.href = url
|
||
link.download = filename
|
||
document.body.appendChild(link)
|
||
link.click()
|
||
document.body.removeChild(link)
|
||
}
|
||
|
||
// 复制到剪贴板
|
||
export async function copyToClipboard(text) {
|
||
try {
|
||
await navigator.clipboard.writeText(text)
|
||
return true
|
||
} catch (error) {
|
||
console.error('复制失败:', error)
|
||
return false
|
||
}
|
||
}
|
||
|
||
// 计算列宽(中文按双字节处理)
|
||
function calcWch(val) {
|
||
const s = (val ?? '').toString()
|
||
let w = 0
|
||
for (const ch of s) w += ch.charCodeAt(0) > 255 ? 2 : 1
|
||
return Math.min(Math.max(w, 8), 60) // 8~60 字符宽
|
||
}
|
||
|
||
// 简单日期格式化(如果字段是 Date 或 ISO 字符串)
|
||
function fmtDate(v) {
|
||
const d = v instanceof Date ? v : (typeof v === 'string' && !isNaN(Date.parse(v)) ? new Date(v) : null)
|
||
if (!d) return v
|
||
const pad = n => (n < 10 ? '0' + n : '' + n)
|
||
return `${d.getFullYear()}-${pad(d.getMonth()+1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`
|
||
}
|
||
|
||
// 真实 .xlsx 导出(中文不会乱码)
|
||
export function exportToExcel(data, headers, filename = '导出.xlsx', sheetName = 'Sheet1') {
|
||
console.log('xlsx导出数据:', data)
|
||
// 动态导入 xlsx 库
|
||
import('xlsx').then(({ utils: XLSXUtils, writeFile: XLSXWriteFile }) => {
|
||
// 1) 规范化数据:按 headers 顺序映射到"显示列名 -> 值"
|
||
const headerLabels = headers.map(h => h.label)
|
||
const rows = (data || []).map(row => {
|
||
const obj = {}
|
||
headers.forEach(h => {
|
||
let v = row?.[h.key]
|
||
// 识别并格式化日期
|
||
v = fmtDate(v)
|
||
|
||
// 复杂对象转字符串
|
||
if (v && typeof v === 'object' && !(v instanceof Date)) {
|
||
try { v = JSON.stringify(v) } catch { v = String(v) }
|
||
}
|
||
|
||
// 公式注入防护(以 = + - @ 开头的文本加前导单引号)
|
||
if (typeof v === 'string' && /^[=+\-@]/.test(v)) v = "'" + v
|
||
|
||
// null/undefined 转为空串,保留 0/false
|
||
if (v === null || v === undefined) v = ''
|
||
obj[h.label] = v
|
||
})
|
||
return obj
|
||
})
|
||
|
||
// 2) 生成工作表
|
||
const ws = XLSXUtils.json_to_sheet(rows, { header: headerLabels })
|
||
|
||
// 3) 列宽:根据表头和数据计算
|
||
const cols = headers.map(h => {
|
||
const headW = calcWch(h.label)
|
||
const dataW = rows.reduce((mx, r) => Math.max(mx, calcWch(r[h.label])), 0)
|
||
return { wch: Math.max(headW, dataW) }
|
||
})
|
||
ws['!cols'] = cols
|
||
|
||
// 4) 冻结首行、开启筛选
|
||
if (ws['!ref']) {
|
||
ws['!freeze'] = { xSplit: 0, ySplit: 1 }
|
||
ws['!autofilter'] = { ref: ws['!ref'] }
|
||
}
|
||
|
||
// 5) 生成工作簿并下载
|
||
const wb = XLSXUtils.book_new()
|
||
XLSXUtils.book_append_sheet(wb, ws, sheetName)
|
||
const safeName = filename.endsWith('.xlsx') ? filename : `${filename}.xlsx`
|
||
XLSXWriteFile(wb, safeName)
|
||
}).catch(error => {
|
||
console.error('Failed to load xlsx library:', error)
|
||
// 可以在这里添加错误提示
|
||
})
|
||
}
|
||
|
||
|