@@ -8,22 +8,25 @@ import {
88 htmlAdapter ,
99 docAdapter ,
1010} from '@/io/export/adapters/exportAdapters' ;
11- import type { ExportFormat } from '@/types/export' ;
11+ import type { ExportFormat , ExportRow } from '@/types/export' ;
1212
1313export function useExport ( ) {
1414 const logStore = useLogStore ( ) ;
1515 const styleStore = useStyleStore ( ) ;
1616 const exportStore = useExportStore ( ) ;
1717
18- function buildRows ( ) {
18+ function buildRows ( ) : ExportRow [ ] {
1919 const { documents } = logStore ;
2020 const { viewSettings, activeRules } = styleStore ;
2121
2222 return flattenLogToRows ( documents , viewSettings , activeRules ) ;
2323 }
2424
2525 async function exportWithAdapter (
26- adapter : ( rows : any , format : ExportFormat ) => any ,
26+ adapter : (
27+ rows : ExportRow [ ] ,
28+ format : ExportFormat ,
29+ ) => string | Blob | Promise < string | Blob > ,
2730 format : ExportFormat ,
2831 fileExtension : string ,
2932 mimeType : string ,
@@ -39,26 +42,51 @@ export function useExport() {
3942
4043 // ===== 对外接口 =====
4144
42- const exportAsText = ( format : ExportFormat = exportStore . activeFormat ) => {
43- exportWithAdapter (
45+ const buildTextContent = (
46+ format : ExportFormat = exportStore . activeFormat ,
47+ ) : string => {
48+ const rows = buildRows ( ) ;
49+ return textAdapter ( rows , format ) ;
50+ } ;
51+
52+ const exportAsText = async (
53+ format : ExportFormat = exportStore . activeFormat ,
54+ ) => {
55+ await exportWithAdapter (
4456 textAdapter ,
4557 format ,
4658 format . fileExtension || '.txt' ,
4759 'text/plain;charset=utf-8' ,
4860 ) ;
4961 } ;
5062
51- const exportAsHtml = ( format : ExportFormat = exportStore . activeFormat ) => {
52- exportWithAdapter (
63+ const copyTextToClipboard = async (
64+ format : ExportFormat = exportStore . activeFormat ,
65+ ) => {
66+ const content = buildTextContent ( format ) ;
67+ await writeTextToClipboard ( content ) ;
68+ } ;
69+
70+ const exportAsHtml = async (
71+ format : ExportFormat = exportStore . activeFormat ,
72+ ) => {
73+ await exportWithAdapter (
5374 htmlAdapter ,
5475 format ,
5576 '.html' ,
5677 'text/html;charset=utf-8' ,
5778 ) ;
5879 } ;
5980
60- const exportAsDoc = ( format : ExportFormat = exportStore . activeFormat ) => {
61- exportWithAdapter ( docAdapter , format , '.doc' , 'application/msword' ) ;
81+ const exportAsDoc = async (
82+ format : ExportFormat = exportStore . activeFormat ,
83+ ) => {
84+ await exportWithAdapter (
85+ docAdapter ,
86+ format ,
87+ '.doc' ,
88+ 'application/msword' ,
89+ ) ;
6290 } ;
6391
6492 const exportAsDocx = async (
@@ -79,9 +107,36 @@ export function useExport() {
79107 exportAsHtml,
80108 exportAsDoc,
81109 exportAsDocx,
110+ copyTextToClipboard,
82111 } ;
83112}
84113
114+ async function writeTextToClipboard ( content : string ) {
115+ if ( navigator . clipboard ?. writeText ) {
116+ await navigator . clipboard . writeText ( content ) ;
117+ return ;
118+ }
119+
120+ const textarea = document . createElement ( 'textarea' ) ;
121+ textarea . value = content ;
122+ textarea . setAttribute ( 'readonly' , '' ) ;
123+ textarea . style . position = 'fixed' ;
124+ textarea . style . left = '-9999px' ;
125+ textarea . style . top = '0' ;
126+
127+ document . body . appendChild ( textarea ) ;
128+ textarea . select ( ) ;
129+
130+ try {
131+ const copied = document . execCommand ( 'copy' ) ;
132+ if ( ! copied ) {
133+ throw new Error ( '复制失败' ) ;
134+ }
135+ } finally {
136+ document . body . removeChild ( textarea ) ;
137+ }
138+ }
139+
85140function downloadFile (
86141 content : string | Blob ,
87142 filename : string ,
0 commit comments