feat: 列宽拖拽 + 筛选栏 + 截图导出 + UI优化
- 新增 v-column-resize 指令,11 张表格均支持拖拽调整列宽 - 工作计划/商机跟单/要客拜访新增筛选栏(客户经理 + 状态) - 汇总栏 chip 可点击筛选,支持重置与计数 - 新增截图导出功能(dom-to-image-more,像素级文字渲染) - 截图范围从标题开始,自动隐藏操作按钮,5px白边 - 截图时页面闪烁动画反馈 - 全局 CSS 完善(列宽手柄、截图模式、捕获动画) - 仪表盘 UI 细节优化 + 亮灯表标签调整 - 登录页 UI 改进 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
/**
|
||||
* useScreenshot — capture a DOM element as PNG and trigger download.
|
||||
*
|
||||
* Uses dom-to-image-more (SVG foreignObject) for pixel-perfect text rendering —
|
||||
* unlike html2canvas, the browser itself paints the text so there's zero offset.
|
||||
*
|
||||
* Usage:
|
||||
* const { capturing, captureEl } = useScreenshot()
|
||||
* <div ref="shotRef">...</div>
|
||||
* <button @click="captureEl(shotRef, 'filename')">截图</button>
|
||||
*/
|
||||
|
||||
import { ref, nextTick } from 'vue'
|
||||
import domtoimage from 'dom-to-image-more'
|
||||
|
||||
export function useScreenshot() {
|
||||
const capturing = ref(false)
|
||||
|
||||
async function captureEl(el: HTMLElement | null, filename: string): Promise<boolean> {
|
||||
if (!el || capturing.value) return false
|
||||
capturing.value = true
|
||||
await nextTick()
|
||||
|
||||
el.classList.add('taking-screenshot')
|
||||
document.body.classList.add('body-capturing')
|
||||
await new Promise((r) => setTimeout(r, 80))
|
||||
|
||||
try {
|
||||
const dataUrl = await domtoimage.toPng(el, {
|
||||
bgColor: '#ffffff',
|
||||
width: el.scrollWidth,
|
||||
height: el.scrollHeight,
|
||||
quality: 1,
|
||||
cacheBust: true,
|
||||
})
|
||||
|
||||
// Pad 5px white border around the image
|
||||
const img = await new Promise<HTMLImageElement>((resolve, reject) => {
|
||||
const i = new Image()
|
||||
i.onload = () => resolve(i)
|
||||
i.onerror = reject
|
||||
i.src = dataUrl
|
||||
})
|
||||
|
||||
const PAD = 5
|
||||
const canvas = document.createElement('canvas')
|
||||
canvas.width = img.width + PAD * 2
|
||||
canvas.height = img.height + PAD * 2
|
||||
const ctx = canvas.getContext('2d')!
|
||||
ctx.fillStyle = '#ffffff'
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height)
|
||||
ctx.drawImage(img, PAD, PAD)
|
||||
|
||||
const link = document.createElement('a')
|
||||
link.download = filename
|
||||
link.href = canvas.toDataURL('image/png')
|
||||
document.body.appendChild(link)
|
||||
link.click()
|
||||
document.body.removeChild(link)
|
||||
return true
|
||||
} catch (e) {
|
||||
console.error('Screenshot failed:', e)
|
||||
return false
|
||||
} finally {
|
||||
el.classList.remove('taking-screenshot')
|
||||
document.body.classList.remove('body-capturing')
|
||||
capturing.value = false
|
||||
}
|
||||
}
|
||||
|
||||
return { capturing, captureEl }
|
||||
}
|
||||
Reference in New Issue
Block a user