@robot-admin/naive-ui-components 0.10.2 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +111 -94
- package/LICENSE +21 -21
- package/README.md +463 -315
- package/README_EN.md +404 -0
- package/SECURITY.md +23 -0
- package/dist/C_ActionBar.cjs +1 -1
- package/dist/C_ActionBar.css +46 -48
- package/dist/C_ActionBar.d.cts +1 -1
- package/dist/C_ActionBar.js +1 -1
- package/dist/C_ActionBar2.cjs +1 -0
- package/dist/C_ActionBar2.js +1 -2
- package/dist/C_AntV.cjs +1 -1
- package/dist/C_AntV.css +3 -3
- package/dist/C_AntV.d.cts +1 -1
- package/dist/C_AntV.js +1 -1
- package/dist/C_AntV2.cjs +4 -0
- package/dist/C_AntV2.js +3 -4
- package/dist/C_AudioPlayer.cjs +1 -1
- package/dist/C_AudioPlayer.css +15 -7
- package/dist/C_AudioPlayer.d.cts +1 -1
- package/dist/C_AudioPlayer.js +1 -1
- package/dist/C_AudioPlayer2.cjs +1 -0
- package/dist/C_AudioPlayer2.js +1 -2
- package/dist/C_AvatarGroup.cjs +1 -1
- package/dist/C_AvatarGroup.css +15 -7
- package/dist/C_AvatarGroup.d.cts +1 -1
- package/dist/C_AvatarGroup2.cjs +1 -0
- package/dist/C_AvatarGroup2.js +1 -2
- package/dist/C_Barcode.cjs +1 -1
- package/dist/C_Barcode.css +0 -2
- package/dist/C_Barcode.d.cts +1 -1
- package/dist/C_Barcode2.cjs +1 -0
- package/dist/C_Barcode2.js +1 -2
- package/dist/C_Breadcrumb.cjs +1 -1
- package/dist/C_Breadcrumb.css +0 -2
- package/dist/C_Breadcrumb.d.cts +2 -2
- package/dist/C_Breadcrumb.d.ts +1 -1
- package/dist/C_Breadcrumb.js +1 -1
- package/dist/C_Breadcrumb2.cjs +1 -0
- package/dist/C_Breadcrumb2.js +1 -2
- package/dist/C_Captcha.cjs +1 -1
- package/dist/C_Captcha.css +46 -21
- package/dist/C_Captcha.d.cts +3 -2
- package/dist/C_Captcha.d.ts +3 -2
- package/dist/C_Captcha.js +1 -1
- package/dist/C_Captcha2.cjs +1 -0
- package/dist/C_Captcha2.js +1 -2
- package/dist/C_Cascade.cjs +1 -1
- package/dist/C_Cascade.css +0 -2
- package/dist/C_Cascade.d.cts +1 -1
- package/dist/C_Cascade.d.ts +1 -1
- package/dist/C_Cascade2.cjs +1 -0
- package/dist/C_Cascade2.js +1 -2
- package/dist/C_Chat.cjs +1 -1
- package/dist/C_Chat.css +0 -2
- package/dist/C_Chat.d.cts +1 -1
- package/dist/C_Chat.d.ts +1 -1
- package/dist/C_Chat.js +1 -1
- package/dist/C_Chat2.cjs +1 -0
- package/dist/C_Chat2.js +1 -2
- package/dist/C_City.cjs +1 -1
- package/dist/C_City.css +28 -30
- package/dist/C_City.d.cts +1 -1
- package/dist/C_City.d.ts +1 -1
- package/dist/C_City2.cjs +1 -0
- package/dist/C_City2.js +1 -2
- package/dist/C_Code.cjs +1 -1
- package/dist/C_Code.css +241 -4
- package/dist/C_Code.d.cts +1 -1
- package/dist/C_Code.d.ts +1 -1
- package/dist/C_Code.js +1 -1
- package/dist/C_Code2.cjs +1 -0
- package/dist/C_Code2.js +1 -2
- package/dist/C_CollapsePanel.cjs +1 -1
- package/dist/C_CollapsePanel.css +12 -6
- package/dist/C_CollapsePanel.d.cts +1 -1
- package/dist/C_CollapsePanel.js +1 -1
- package/dist/C_CollapsePanel2.cjs +1 -0
- package/dist/C_CollapsePanel2.js +1 -2
- package/dist/C_ContextMenu.cjs +1 -1
- package/dist/C_ContextMenu.css +16 -18
- package/dist/C_ContextMenu.d.cts +1 -1
- package/dist/C_ContextMenu.d.ts +1 -1
- package/dist/C_ContextMenu.js +1 -1
- package/dist/C_ContextMenu2.cjs +1 -0
- package/dist/C_ContextMenu2.js +1 -2
- package/dist/C_Cron.cjs +1 -1
- package/dist/C_Cron.css +18 -8
- package/dist/C_Cron.d.cts +1 -1
- package/dist/C_Cron.js +1 -1
- package/dist/C_Cron2.cjs +1 -0
- package/dist/C_Cron2.js +1 -2
- package/dist/C_Date.cjs +1 -1
- package/dist/C_Date.css +1 -0
- package/dist/C_Date.d.cts +2 -2
- package/dist/C_Date.d.ts +2 -2
- package/dist/C_Date2.cjs +1 -0
- package/dist/C_Date2.js +1 -2
- package/dist/C_Draggable.cjs +1 -1
- package/dist/C_Draggable.css +9 -5
- package/dist/C_Draggable.d.cts +1 -1
- package/dist/C_Draggable2.cjs +1 -0
- package/dist/C_Draggable2.js +1 -2
- package/dist/C_Editor.cjs +1 -1
- package/dist/C_Editor.css +80 -67
- package/dist/C_Editor.d.cts +1 -1
- package/dist/C_Editor.d.ts +1 -1
- package/dist/C_Editor2.cjs +1 -0
- package/dist/C_Editor2.js +1 -2
- package/dist/C_FilePreview.cjs +1 -1
- package/dist/C_FilePreview.css +0 -2
- package/dist/C_FilePreview.d.cts +1 -1
- package/dist/C_FilePreview.js +1 -1
- package/dist/C_FilePreview2.cjs +1 -0
- package/dist/C_FilePreview2.js +1 -2
- package/dist/C_Form.base.css +980 -0
- package/dist/C_Form.cjs +1 -1
- package/dist/C_Form.css +256 -155
- package/dist/C_Form.d.cts +2 -2
- package/dist/C_Form.d.ts +2 -2
- package/dist/C_Form.js +1 -1
- package/dist/C_Form2.cjs +1 -0
- package/dist/C_Form2.js +1 -2
- package/dist/C_FormSearch.cjs +1 -1
- package/dist/C_FormSearch.css +47 -47
- package/dist/C_FormSearch.d.cts +2 -2
- package/dist/C_FormSearch.d.ts +2 -2
- package/dist/C_FormSearch2.cjs +1 -0
- package/dist/C_FormSearch2.js +1 -2
- package/dist/C_FormulaEditor.cjs +1 -1
- package/dist/C_FormulaEditor.css +64 -38
- package/dist/C_FormulaEditor.d.cts +1 -1
- package/dist/C_FormulaEditor.js +1 -1
- package/dist/C_FormulaEditor2.cjs +2 -0
- package/dist/C_FormulaEditor2.js +2 -2
- package/dist/C_FullCalendar.cjs +1 -1
- package/dist/C_FullCalendar.css +0 -2
- package/dist/C_FullCalendar.d.cts +1 -1
- package/dist/C_FullCalendar2.cjs +1 -0
- package/dist/C_FullCalendar2.js +1 -2
- package/dist/C_GlobalSearch.cjs +1 -1
- package/dist/C_GlobalSearch.css +111 -113
- package/dist/C_GlobalSearch.d.cts +1 -1
- package/dist/C_GlobalSearch2.cjs +1 -0
- package/dist/C_GlobalSearch2.js +1 -2
- package/dist/C_Guide.cjs +1 -1
- package/dist/C_Guide.css +1 -0
- package/dist/C_Guide.d.cts +1 -1
- package/dist/C_Guide.d.ts +1 -1
- package/dist/C_Guide.js +1 -1
- package/dist/C_Guide2.cjs +1 -0
- package/dist/C_Guide2.js +1 -2
- package/dist/C_Icon.cjs +1 -1
- package/dist/C_Icon.css +58 -0
- package/dist/C_Icon.d.cts +1 -1
- package/dist/C_Icon.d.ts +1 -1
- package/dist/C_Icon2.cjs +1 -0
- package/dist/C_Icon2.js +1 -2
- package/dist/C_ImageCropper.cjs +1 -1
- package/dist/C_ImageCropper.css +0 -2
- package/dist/C_ImageCropper.d.cts +1 -1
- package/dist/C_ImageCropper.js +1 -1
- package/dist/C_ImageCropper2.cjs +1 -0
- package/dist/C_ImageCropper2.js +1 -2
- package/dist/C_Language.cjs +1 -1
- package/dist/C_Language.css +1 -0
- package/dist/C_Language.d.cts +1 -1
- package/dist/C_Language.d.ts +1 -1
- package/dist/C_Language.js +1 -1
- package/dist/C_Language2.cjs +1 -0
- package/dist/C_Language2.js +1 -2
- package/dist/C_Login.cjs +1 -1
- package/dist/C_Login.css +92 -76
- package/dist/C_Login.d.cts +1 -1
- package/dist/C_Login.d.ts +1 -1
- package/dist/C_Login.js +1 -1
- package/dist/C_Login2.cjs +1 -0
- package/dist/C_Login2.js +1 -2
- package/dist/C_Map.cjs +1 -1
- package/dist/C_Map.css +665 -5
- package/dist/C_Map.d.cts +1 -1
- package/dist/C_Map2.cjs +1 -0
- package/dist/C_Map2.js +1 -2
- package/dist/C_Markdown.cjs +1 -1
- package/dist/C_Markdown.css +940 -35
- package/dist/C_Markdown.d.cts +1 -1
- package/dist/C_Markdown.d.ts +1 -1
- package/dist/C_Markdown2.cjs +1 -0
- package/dist/C_Markdown2.js +1 -2
- package/dist/C_Menu.cjs +1 -1
- package/dist/C_Menu.css +1 -0
- package/dist/C_Menu.d.cts +3 -3
- package/dist/C_Menu.d.ts +3 -3
- package/dist/C_Menu2.cjs +1 -0
- package/dist/C_Menu2.js +1 -2
- package/dist/C_NotificationCenter.cjs +1 -1
- package/dist/C_NotificationCenter.css +95 -47
- package/dist/C_NotificationCenter.d.cts +1 -1
- package/dist/C_NotificationCenter.js +1 -1
- package/dist/C_NotificationCenter2.cjs +1 -0
- package/dist/C_NotificationCenter2.js +1 -2
- package/dist/C_OrgChart.cjs +1 -1
- package/dist/C_OrgChart.css +6 -4
- package/dist/C_OrgChart.d.cts +1 -1
- package/dist/C_OrgChart.d.ts +1 -1
- package/dist/C_OrgChart2.cjs +1 -0
- package/dist/C_OrgChart2.js +1 -2
- package/dist/C_Progress.cjs +1 -1
- package/dist/C_Progress.css +1 -0
- package/dist/C_Progress.d.cts +1 -1
- package/dist/C_Progress.d.ts +1 -1
- package/dist/C_Progress2.cjs +1 -0
- package/dist/C_Progress2.js +1 -2
- package/dist/C_QRCode.cjs +1 -1
- package/dist/C_QRCode.css +8 -10
- package/dist/C_QRCode.d.cts +1 -1
- package/dist/C_QRCode2.cjs +1 -0
- package/dist/C_QRCode2.js +1 -2
- package/dist/C_Signature.cjs +1 -1
- package/dist/C_Signature.css +0 -2
- package/dist/C_Signature.d.cts +1 -1
- package/dist/C_Signature.js +1 -1
- package/dist/C_Signature2.cjs +1 -0
- package/dist/C_Signature2.js +1 -2
- package/dist/C_Skeleton.cjs +1 -1
- package/dist/C_Skeleton.css +0 -2
- package/dist/C_Skeleton.d.cts +1 -1
- package/dist/C_Skeleton.d.ts +1 -1
- package/dist/C_Skeleton2.cjs +1 -0
- package/dist/C_Skeleton2.js +1 -2
- package/dist/C_SplitPane.cjs +1 -1
- package/dist/C_SplitPane.css +27 -11
- package/dist/C_SplitPane.d.cts +1 -1
- package/dist/C_SplitPane.js +1 -1
- package/dist/C_SplitPane2.cjs +1 -0
- package/dist/C_SplitPane2.js +1 -2
- package/dist/C_Steps.cjs +1 -1
- package/dist/C_Steps.css +37 -39
- package/dist/C_Steps.d.cts +1 -1
- package/dist/C_Steps.d.ts +1 -1
- package/dist/C_Steps2.cjs +1 -0
- package/dist/C_Steps2.js +1 -2
- package/dist/C_Table.base.css +1588 -0
- package/dist/C_Table.cjs +1 -1
- package/dist/C_Table.css +1202 -112
- package/dist/C_Table.d.cts +2 -2
- package/dist/C_Table.d.ts +11 -2
- package/dist/C_Table.js +1 -1
- package/dist/C_TagsView.cjs +1 -1
- package/dist/C_TagsView.css +44 -40
- package/dist/C_TagsView.d.cts +2 -2
- package/dist/C_TagsView.d.ts +2 -2
- package/dist/C_TagsView.js +1 -1
- package/dist/C_TagsView2.cjs +1 -0
- package/dist/C_TagsView2.js +1 -2
- package/dist/C_Theme.cjs +1 -1
- package/dist/C_Theme.css +1 -0
- package/dist/C_Theme.d.cts +1 -1
- package/dist/C_Theme.d.ts +1 -1
- package/dist/C_Theme.js +1 -1
- package/dist/C_Theme2.cjs +1 -0
- package/dist/C_Theme2.js +1 -2
- package/dist/C_Time.cjs +1 -1
- package/dist/C_Time.css +0 -2
- package/dist/C_Time.d.cts +2 -2
- package/dist/C_Time.d.ts +2 -2
- package/dist/C_Time2.cjs +1 -0
- package/dist/C_Time2.js +1 -2
- package/dist/C_Timeline.cjs +1 -1
- package/dist/C_Timeline.css +44 -46
- package/dist/C_Timeline.d.cts +1 -1
- package/dist/C_Timeline.js +1 -1
- package/dist/C_Timeline2.cjs +1 -0
- package/dist/C_Timeline2.js +1 -2
- package/dist/C_Transfer.cjs +1 -1
- package/dist/C_Transfer.css +21 -9
- package/dist/C_Transfer.d.cts +1 -1
- package/dist/C_Transfer.js +1 -1
- package/dist/C_Transfer2.cjs +1 -0
- package/dist/C_Transfer2.js +1 -2
- package/dist/C_Tree.cjs +1 -1
- package/dist/C_Tree.css +0 -2
- package/dist/C_Tree.d.cts +1 -1
- package/dist/C_Tree.js +1 -1
- package/dist/C_Tree2.cjs +1 -0
- package/dist/C_Tree2.js +1 -2
- package/dist/C_Upload.cjs +1 -1
- package/dist/C_Upload.css +17 -17
- package/dist/C_Upload.d.cts +1 -1
- package/dist/C_Upload.js +1 -1
- package/dist/C_Upload2.cjs +1 -0
- package/dist/C_Upload2.js +1 -25
- package/dist/C_VideoPlayer.cjs +1 -1
- package/dist/C_VideoPlayer.css +35 -24
- package/dist/C_VideoPlayer.d.cts +2 -2
- package/dist/C_VideoPlayer.d.ts +2 -2
- package/dist/C_VideoPlayer.js +1 -1
- package/dist/C_VideoPlayer2.cjs +3 -0
- package/dist/C_VideoPlayer2.js +3 -4
- package/dist/C_VtableGantt.cjs +1 -1
- package/dist/C_VtableGantt.css +15 -7
- package/dist/C_VtableGantt.d.cts +1 -1
- package/dist/C_VtableGantt.d.ts +1 -1
- package/dist/C_VtableGantt.js +1 -1
- package/dist/C_VtableGantt2.cjs +1 -0
- package/dist/C_VtableGantt2.js +1 -2
- package/dist/C_WaterFall.cjs +1 -1
- package/dist/C_WaterFall.css +15 -17
- package/dist/C_WaterFall.d.cts +1 -1
- package/dist/C_WaterFall2.cjs +1 -0
- package/dist/C_WaterFall2.js +1 -2
- package/dist/C_WorkFlow.cjs +1 -1
- package/dist/C_WorkFlow.css +257 -197
- package/dist/C_WorkFlow.d.cts +1 -1
- package/dist/C_WorkFlow.js +1 -1
- package/dist/C_WorkFlow2.cjs +1 -0
- package/dist/C_WorkFlow2.js +1 -2
- package/dist/city.cjs +1 -0
- package/dist/city.js +1 -2
- package/dist/config.cjs +1 -0
- package/dist/config.d.cts +33 -0
- package/dist/config.d.ts +33 -0
- package/dist/config.js +1 -0
- package/dist/constants.d.cts +272 -0
- package/dist/constants.d.ts +2 -3
- package/dist/constants2.d.cts +177 -0
- package/dist/constants2.d.ts +3 -4
- package/dist/constants3.d.cts +479 -0
- package/dist/constants3.d.ts +16 -12
- package/dist/constants4.d.cts +420 -0
- package/dist/constants4.d.ts +27 -37
- package/dist/constants5.d.cts +491 -0
- package/dist/constants5.d.ts +20 -4
- package/dist/data.cjs +1 -0
- package/dist/data.d.cts +67 -0
- package/dist/data.d.ts +12 -12
- package/dist/data.js +1 -0
- package/dist/export-helper.cjs +1 -0
- package/dist/helpers.cjs +1 -0
- package/dist/helpers.js +1 -0
- package/dist/html.cjs +1 -0
- package/dist/html.js +1 -0
- package/dist/images/marker-icon-2x.png +0 -0
- package/dist/images/marker-icon.png +0 -0
- package/dist/images/marker-shadow.png +0 -0
- package/dist/index.cjs +1 -2
- package/dist/index.d.cts +60 -99
- package/dist/index.d.ts +75 -164
- package/dist/index.js +1 -2
- package/dist/index.vue.d.cts +79 -0
- package/dist/index.vue.d.ts +3 -4
- package/dist/index10.vue.d.cts +47 -0
- package/dist/index10.vue.d.ts +80 -40
- package/dist/index11.vue.d.cts +88 -0
- package/dist/index11.vue.d.ts +68 -78
- package/dist/index12.vue.d.cts +79 -0
- package/dist/index12.vue.d.ts +49 -45
- package/dist/index13.vue.d.cts +64 -0
- package/dist/index13.vue.d.ts +99 -34
- package/dist/index14.vue.d.cts +106 -0
- package/dist/index14.vue.d.ts +82 -99
- package/dist/index15.vue.d.cts +91 -0
- package/dist/index15.vue.d.ts +25 -83
- package/dist/index16.vue.d.cts +34 -0
- package/dist/index16.vue.d.ts +113 -24
- package/dist/index17.vue.d.cts +124 -0
- package/dist/index17.vue.d.ts +76 -110
- package/dist/index18.vue.d.cts +83 -0
- package/dist/index18.vue.d.ts +67 -73
- package/dist/index19.vue.d.cts +101 -0
- package/dist/index19.vue.d.ts +93 -59
- package/dist/index2.vue.d.cts +82 -0
- package/dist/index2.vue.d.ts +7 -8
- package/dist/index20.vue.d.cts +54 -0
- package/dist/index20.vue.d.ts +40 -88
- package/dist/index21.vue.d.cts +103 -0
- package/dist/index21.vue.d.ts +89 -41
- package/dist/index22.vue.d.cts +45 -0
- package/dist/index22.vue.d.ts +37 -96
- package/dist/index23.vue.d.cts +19 -0
- package/dist/index23.vue.d.ts +8 -35
- package/dist/{index28.vue.d.ts → index24.vue.d.cts} +4 -5
- package/dist/index24.vue.d.ts +650 -86
- package/dist/index25.vue.d.cts +96 -0
- package/dist/index25.vue.d.ts +86 -10
- package/dist/index26.vue.d.cts +111 -0
- package/dist/index26.vue.d.ts +4 -5
- package/dist/index27.vue.d.cts +80 -0
- package/dist/index27.vue.d.ts +2 -3
- package/dist/index3.vue.d.cts +87 -0
- package/dist/index3.vue.d.ts +4 -5
- package/dist/index4.vue.d.cts +37 -0
- package/dist/index4.vue.d.ts +6 -7
- package/dist/index5.vue.d.cts +133 -0
- package/dist/index5.vue.d.ts +2 -3
- package/dist/index6.vue.d.cts +29 -0
- package/dist/index6.vue.d.ts +25 -38
- package/dist/index7.vue.d.cts +32 -0
- package/dist/index7.vue.d.ts +117 -23
- package/dist/index8.vue.d.cts +127 -0
- package/dist/index8.vue.d.ts +17 -111
- package/dist/index9.vue.d.cts +34 -0
- package/dist/index9.vue.d.ts +38 -26
- package/dist/public.d.ts +166 -0
- package/dist/resolver.cjs +1 -2
- package/dist/resolver.d.cts +6 -4
- package/dist/resolver.d.ts +6 -4
- package/dist/resolver.js +1 -2
- package/dist/storage.cjs +1 -0
- package/dist/storage.js +1 -2
- package/dist/style.css +9864 -7702
- package/dist/types.d.cts +107 -0
- package/dist/types.d.ts +52 -102
- package/dist/types2.d.cts +58 -0
- package/dist/useCalendarEvents.d.cts +150 -0
- package/dist/useCalendarEvents.d.ts +3 -4
- package/dist/useCollapsePanel.d.cts +133 -0
- package/dist/useCollapsePanel.d.ts +2 -3
- package/dist/useCropperCore.d.cts +104 -0
- package/dist/useCropperCore.d.ts +11 -9
- package/dist/useDraggableLayout.d.cts +196 -0
- package/dist/useDraggableLayout.d.ts +17 -15
- package/dist/useDynamicFormState.d.cts +749 -0
- package/dist/useDynamicFormState.d.ts +234 -112
- package/dist/useEdgeInteraction.d.cts +324 -0
- package/dist/useEdgeInteraction.d.ts +6 -7
- package/dist/useFullscreen.d.cts +165 -0
- package/dist/useFullscreen.d.ts +1 -2
- package/dist/useGlobalSearch.d.cts +110 -0
- package/dist/useGlobalSearch.d.ts +17 -9
- package/dist/useInfiniteScroll.d.cts +177 -0
- package/dist/useInfiniteScroll.d.ts +13 -5
- package/dist/useQRCode.d.cts +89 -0
- package/dist/useQRCode.d.ts +5 -3
- package/dist/useSearchState.d.cts +871 -0
- package/dist/useSearchState.d.ts +830 -30
- package/dist/useSignatureHistory.d.cts +197 -0
- package/dist/useSignatureHistory.d.ts +10 -5
- package/dist/useSplitResize.d.cts +157 -0
- package/dist/useSplitResize.d.ts +3 -4
- package/dist/useTableQuery.cjs +3 -0
- package/dist/{useModalEdit.d.ts → useTableQuery.d.cts} +624 -211
- package/dist/useTableQuery.d.ts +1721 -0
- package/dist/useTableQuery.js +3 -0
- package/dist/useTimeSelection.d.cts +116 -0
- package/dist/useTimeSelection.d.ts +20 -9
- package/dist/useTreeOperations.d.cts +185 -0
- package/dist/useTreeOperations.d.ts +13 -11
- package/dist/useWorkflowValidation.d.cts +1051 -0
- package/dist/useWorkflowValidation.d.ts +62 -63
- package/dist/verification.d.cts +58 -0
- package/dist/verification.d.ts +58 -0
- package/package.json +102 -69
- package/dist/C_ActionBar-BAcfOfRw.css.map +0 -1
- package/dist/C_ActionBar-DG2HW7t5.css.map +0 -1
- package/dist/C_ActionBar.js.map +0 -1
- package/dist/C_ActionBar2.js.map +0 -1
- package/dist/C_AntV-D_jTK8oZ.css.map +0 -1
- package/dist/C_AntV-DanTAq22.css.map +0 -1
- package/dist/C_AntV.js.map +0 -1
- package/dist/C_AntV2.js.map +0 -1
- package/dist/C_AudioPlayer-BnYIJXPD.css.map +0 -1
- package/dist/C_AudioPlayer-Cj4lUdZo.css.map +0 -1
- package/dist/C_AudioPlayer.js.map +0 -1
- package/dist/C_AudioPlayer2.js.map +0 -1
- package/dist/C_AvatarGroup-B9d-GJ9c.css.map +0 -1
- package/dist/C_AvatarGroup-D3PwsKME.css.map +0 -1
- package/dist/C_AvatarGroup.js.map +0 -1
- package/dist/C_AvatarGroup2.js.map +0 -1
- package/dist/C_Barcode-CAU2mFcx.css.map +0 -1
- package/dist/C_Barcode-D2oJaEg3.css.map +0 -1
- package/dist/C_Barcode.js.map +0 -1
- package/dist/C_Barcode2.js.map +0 -1
- package/dist/C_Breadcrumb-BiH0d9AI.css.map +0 -1
- package/dist/C_Breadcrumb-DOcLt9uX.css.map +0 -1
- package/dist/C_Breadcrumb.js.map +0 -1
- package/dist/C_Breadcrumb2.js.map +0 -1
- package/dist/C_Captcha-B3yrtG7t.css.map +0 -1
- package/dist/C_Captcha-D4hDdWDu.css.map +0 -1
- package/dist/C_Captcha.js.map +0 -1
- package/dist/C_Captcha2.js.map +0 -1
- package/dist/C_Cascade-CmCrLVft.css.map +0 -1
- package/dist/C_Cascade-U6A5AJJb.css.map +0 -1
- package/dist/C_Cascade.js.map +0 -1
- package/dist/C_Cascade2.js.map +0 -1
- package/dist/C_Chat-DeUv6uuI.css.map +0 -1
- package/dist/C_Chat-DwatUQqu.css.map +0 -1
- package/dist/C_Chat.js.map +0 -1
- package/dist/C_Chat2.js.map +0 -1
- package/dist/C_City-DdkX6u64.css.map +0 -1
- package/dist/C_City-iP-dIvui.css.map +0 -1
- package/dist/C_City.js.map +0 -1
- package/dist/C_City2.js.map +0 -1
- package/dist/C_Code-BWmJMNS7.css.map +0 -1
- package/dist/C_Code-k14vjgVl.css.map +0 -1
- package/dist/C_Code.js.map +0 -1
- package/dist/C_Code2.js.map +0 -1
- package/dist/C_CollapsePanel-BSKcWSmY.css.map +0 -1
- package/dist/C_CollapsePanel-DRvRq8tB.css.map +0 -1
- package/dist/C_CollapsePanel.js.map +0 -1
- package/dist/C_CollapsePanel2.js.map +0 -1
- package/dist/C_ContextMenu-C9iuxG2n.css.map +0 -1
- package/dist/C_ContextMenu-CD0iaSju.css.map +0 -1
- package/dist/C_ContextMenu.js.map +0 -1
- package/dist/C_ContextMenu2.js.map +0 -1
- package/dist/C_Cron-BIQ2By9v.css.map +0 -1
- package/dist/C_Cron-BNSAGD6A.css.map +0 -1
- package/dist/C_Cron.js.map +0 -1
- package/dist/C_Cron2.js.map +0 -1
- package/dist/C_Date.js.map +0 -1
- package/dist/C_Date2.js.map +0 -1
- package/dist/C_Draggable-BDAbk4s5.css.map +0 -1
- package/dist/C_Draggable-UhfDLXop.css.map +0 -1
- package/dist/C_Draggable.js.map +0 -1
- package/dist/C_Draggable2.js.map +0 -1
- package/dist/C_Editor-CZOaChru.css.map +0 -1
- package/dist/C_Editor-kJAQq5z6.css.map +0 -1
- package/dist/C_Editor.js.map +0 -1
- package/dist/C_Editor2.js.map +0 -1
- package/dist/C_FilePreview-Bs_omgJS.css.map +0 -1
- package/dist/C_FilePreview-DbwoyF2j.css.map +0 -1
- package/dist/C_FilePreview.js.map +0 -1
- package/dist/C_FilePreview2.js.map +0 -1
- package/dist/C_Form-B_2ql62V.css.map +0 -1
- package/dist/C_Form-CX-7xsz3.css.map +0 -1
- package/dist/C_Form.js.map +0 -1
- package/dist/C_Form2.js.map +0 -1
- package/dist/C_FormSearch-C3F8peAY.css.map +0 -1
- package/dist/C_FormSearch-qW56bJPo.css.map +0 -1
- package/dist/C_FormSearch.js.map +0 -1
- package/dist/C_FormSearch2.js.map +0 -1
- package/dist/C_FormulaEditor-ChOvDbsZ.css.map +0 -1
- package/dist/C_FormulaEditor-mfiIUDY4.css.map +0 -1
- package/dist/C_FormulaEditor.js.map +0 -1
- package/dist/C_FormulaEditor2.js.map +0 -1
- package/dist/C_FullCalendar-C2nsqrgS.css.map +0 -1
- package/dist/C_FullCalendar-DdFtXVhy.css.map +0 -1
- package/dist/C_FullCalendar.js.map +0 -1
- package/dist/C_FullCalendar2.js.map +0 -1
- package/dist/C_GlobalSearch-Dq4Wo01K.css.map +0 -1
- package/dist/C_GlobalSearch-RB7J43gu.css.map +0 -1
- package/dist/C_GlobalSearch.js.map +0 -1
- package/dist/C_GlobalSearch2.js.map +0 -1
- package/dist/C_Guide.js.map +0 -1
- package/dist/C_Guide2.js.map +0 -1
- package/dist/C_Icon.js.map +0 -1
- package/dist/C_Icon2.js.map +0 -1
- package/dist/C_ImageCropper-CdTX2nxU.css.map +0 -1
- package/dist/C_ImageCropper-ilOqPklJ.css.map +0 -1
- package/dist/C_ImageCropper.js.map +0 -1
- package/dist/C_ImageCropper2.js.map +0 -1
- package/dist/C_Language.js.map +0 -1
- package/dist/C_Language2.js.map +0 -1
- package/dist/C_Login-BrQBs_m4.css.map +0 -1
- package/dist/C_Login-xMI1_ojE.css.map +0 -1
- package/dist/C_Login.js.map +0 -1
- package/dist/C_Login2.js.map +0 -1
- package/dist/C_Map-CWMMN58_.css.map +0 -1
- package/dist/C_Map-xSR2H-9o.css.map +0 -1
- package/dist/C_Map.js.map +0 -1
- package/dist/C_Map2.js.map +0 -1
- package/dist/C_Markdown-C7lTVJ1S.css.map +0 -1
- package/dist/C_Markdown-CZDm_baQ.css.map +0 -1
- package/dist/C_Markdown.js.map +0 -1
- package/dist/C_Markdown2.js.map +0 -1
- package/dist/C_Menu.js.map +0 -1
- package/dist/C_Menu2.js.map +0 -1
- package/dist/C_NotificationCenter-D7GGGWg7.css.map +0 -1
- package/dist/C_NotificationCenter-SSmeHA45.css.map +0 -1
- package/dist/C_NotificationCenter.js.map +0 -1
- package/dist/C_NotificationCenter2.js.map +0 -1
- package/dist/C_OrgChart-BXEp4i4w.css.map +0 -1
- package/dist/C_OrgChart-DqBufOv5.css.map +0 -1
- package/dist/C_OrgChart.js.map +0 -1
- package/dist/C_OrgChart2.js.map +0 -1
- package/dist/C_Progress.js.map +0 -1
- package/dist/C_Progress2.js.map +0 -1
- package/dist/C_QRCode-B_1lHUdx.css.map +0 -1
- package/dist/C_QRCode-CuQRYu0s.css.map +0 -1
- package/dist/C_QRCode.js.map +0 -1
- package/dist/C_QRCode2.js.map +0 -1
- package/dist/C_Signature-Bp-RBpAl.css.map +0 -1
- package/dist/C_Signature-Cb2VW1ok.css.map +0 -1
- package/dist/C_Signature.js.map +0 -1
- package/dist/C_Signature2.js.map +0 -1
- package/dist/C_Skeleton-BJoFYwrF.css.map +0 -1
- package/dist/C_Skeleton-Djsjw8XY.css.map +0 -1
- package/dist/C_Skeleton.js.map +0 -1
- package/dist/C_Skeleton2.js.map +0 -1
- package/dist/C_SplitPane-CgGWYsRE.css.map +0 -1
- package/dist/C_SplitPane-DGf6WEeR.css.map +0 -1
- package/dist/C_SplitPane.js.map +0 -1
- package/dist/C_SplitPane2.js.map +0 -1
- package/dist/C_Steps-27Exh7PM.css.map +0 -1
- package/dist/C_Steps-DU9ZsFrs.css.map +0 -1
- package/dist/C_Steps.js.map +0 -1
- package/dist/C_Steps2.js.map +0 -1
- package/dist/C_Table--kbQaaBv.css.map +0 -1
- package/dist/C_Table-D631kdXC.css.map +0 -1
- package/dist/C_Table.js.map +0 -1
- package/dist/C_Table2.js +0 -4
- package/dist/C_Table2.js.map +0 -1
- package/dist/C_TagsView-DtGtYhBH.css.map +0 -1
- package/dist/C_TagsView-s1dnSJAV.css.map +0 -1
- package/dist/C_TagsView.js.map +0 -1
- package/dist/C_TagsView2.js.map +0 -1
- package/dist/C_Theme.js.map +0 -1
- package/dist/C_Theme2.js.map +0 -1
- package/dist/C_Time-BQ9PGy8B.css.map +0 -1
- package/dist/C_Time-CO73krC6.css.map +0 -1
- package/dist/C_Time.js.map +0 -1
- package/dist/C_Time2.js.map +0 -1
- package/dist/C_Timeline-DdESmqwL.css.map +0 -1
- package/dist/C_Timeline-irQcO-b7.css.map +0 -1
- package/dist/C_Timeline.js.map +0 -1
- package/dist/C_Timeline2.js.map +0 -1
- package/dist/C_Transfer-11y3k-WD.css.map +0 -1
- package/dist/C_Transfer-EzdHzZNv.css.map +0 -1
- package/dist/C_Transfer.js.map +0 -1
- package/dist/C_Transfer2.js.map +0 -1
- package/dist/C_Tree-CsXgGfhn.css.map +0 -1
- package/dist/C_Tree-P7eRpnOa.css.map +0 -1
- package/dist/C_Tree.js.map +0 -1
- package/dist/C_Tree2.js.map +0 -1
- package/dist/C_Upload-CHjiVVh7.css.map +0 -1
- package/dist/C_Upload-DE3OLsZD.css.map +0 -1
- package/dist/C_Upload.js.map +0 -1
- package/dist/C_Upload2.js.map +0 -1
- package/dist/C_VideoPlayer-CnaNOFtW.css.map +0 -1
- package/dist/C_VideoPlayer-cnP88zNV.css.map +0 -1
- package/dist/C_VideoPlayer.js.map +0 -1
- package/dist/C_VideoPlayer2.js.map +0 -1
- package/dist/C_VtableGantt-CZlJgvpC.css.map +0 -1
- package/dist/C_VtableGantt-DKfQkql0.css.map +0 -1
- package/dist/C_VtableGantt.js.map +0 -1
- package/dist/C_VtableGantt2.js.map +0 -1
- package/dist/C_WaterFall-BJ_39ext.css.map +0 -1
- package/dist/C_WaterFall-cYc1vntE.css.map +0 -1
- package/dist/C_WaterFall.js.map +0 -1
- package/dist/C_WaterFall2.js.map +0 -1
- package/dist/C_WorkFlow-BFzRGGhJ.css.map +0 -1
- package/dist/C_WorkFlow-DSyCOvRp.css.map +0 -1
- package/dist/C_WorkFlow.js.map +0 -1
- package/dist/C_WorkFlow2.js.map +0 -1
- package/dist/city.js.map +0 -1
- package/dist/index.cjs.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/index2.d.ts +0 -120
- package/dist/resolver.cjs.map +0 -1
- package/dist/resolver.js.map +0 -1
- package/dist/storage.js.map +0 -1
- /package/dist/{chunk.js → chunk.cjs} +0 -0
package/dist/C_Editor2.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"C_Editor2.js","names":["editorId"],"sources":["../src/components/C_Editor/index.vue","../src/components/C_Editor/index.vue"],"sourcesContent":["<!--\n * @Author: ChenYu ycyplus@gmail.com\n * @Date: 2025-06-01\n * @Description: 富文本编辑器组件(简化主题版)\n * @Migration: naive-ui-components 组件库迁移版本\n * Copyright (c) 2025 by CHENY, All Rights Reserved.\n-->\n<template>\n <div\n ref=\"editorContainer\"\n :id=\"editorId\"\n v-show=\"isInitialized\"\n class=\"w-full\"\n :class=\"{ 'editor-dark': isDark }\"\n @focusin=\"handleEditorFocus\"\n @focusout=\"handleEditorBlur\"\n ></div>\n</template>\n\n<script setup lang=\"ts\">\nimport {\n ref,\n computed,\n watch,\n nextTick,\n onMounted,\n onBeforeUnmount,\n readonly,\n} from \"vue\";\nimport E from \"wangeditor\";\n\ndefineOptions({ name: \"C_Editor\" });\n\ninterface Props {\n editorId: string;\n modelValue?: string;\n placeholder?: string;\n disabled?: boolean;\n readonly?: boolean;\n height?: number;\n theme?: \"light\" | \"dark\";\n}\n\ninterface Emits {\n (e: \"update:modelValue\", value: string): void;\n (e: \"editor-mounted\", editor: any): void;\n (e: \"editor-change\", html: string): void;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n modelValue: \"\",\n placeholder: \"\",\n disabled: false,\n readonly: false,\n height: 240,\n theme: \"light\",\n});\n\nconst emit = defineEmits<Emits>();\n\nconst editorContainer = ref<HTMLElement | null>(null);\nconst editorInstance = ref<any>(null);\nconst isInitialized = ref<boolean>(false);\n\nconst isDark = computed(() => props.theme === \"dark\");\n\nconst initializeEditor = (): void => {\n if (!editorContainer.value || isInitialized.value) return;\n\n try {\n const editor = new E(editorContainer.value);\n const editorConfig = editor.config as any;\n editorConfig.placeholder = props.placeholder;\n editorConfig.height = props.height - 50;\n\n editorConfig.onchange = (html: string) => {\n emit(\"update:modelValue\", html);\n emit(\"editor-change\", html);\n };\n\n editor.create();\n\n nextTick(() => {\n if (props.modelValue) {\n editor.txt.html(props.modelValue);\n }\n if (props.readonly) {\n editor.disable();\n }\n editorInstance.value = editor;\n isInitialized.value = true;\n emit(\"editor-mounted\", editor);\n });\n } catch (error) {\n console.error(`[C_Editor] 编辑器初始化失败: ${props.editorId}`, error);\n }\n};\n\nconst destroyEditor = (): void => {\n if (editorInstance.value && isInitialized.value) {\n try {\n editorInstance.value.destroy();\n editorInstance.value = null;\n isInitialized.value = false;\n } catch (error) {\n console.error(`[C_Editor] 编辑器销毁失败: ${props.editorId}`, error);\n }\n }\n};\n\nconst setContent = (html: string): void => {\n if (editorInstance.value && isInitialized.value) {\n try {\n editorInstance.value.txt.html(html);\n } catch (error) {\n console.warn(`[C_Editor] 设置编辑器内容失败: ${props.editorId}`, error);\n }\n }\n};\n\nconst getContent = (): string => {\n if (editorInstance.value && isInitialized.value) {\n try {\n return editorInstance.value.txt.html();\n } catch (error) {\n console.warn(`[C_Editor] 获取编辑器内容失败: ${props.editorId}`, error);\n return \"\";\n }\n }\n return \"\";\n};\n\nwatch(\n () => props.modelValue,\n (newValue) => {\n if (editorInstance.value && isInitialized.value) {\n const currentContent = editorInstance.value.txt.html();\n if (currentContent !== newValue) {\n editorInstance.value.txt.html(newValue || \"\");\n }\n }\n },\n);\n\nwatch(\n () => props.disabled,\n (disabled) => {\n if (editorInstance.value && isInitialized.value) {\n try {\n if (disabled) editorInstance.value.disable();\n else editorInstance.value.enable();\n } catch (error) {\n console.warn(`[C_Editor] 设置编辑器状态失败`, error);\n }\n }\n },\n);\n\nwatch(\n () => props.readonly,\n (readonlyVal) => {\n if (editorInstance.value && isInitialized.value) {\n try {\n if (readonlyVal) editorInstance.value.disable();\n else editorInstance.value.enable();\n } catch (error) {\n console.warn(`[C_Editor] 设置编辑器只读状态失败`, error);\n }\n }\n },\n);\n\nconst handleEditorFocus = (): void => {\n if (!editorContainer.value) return;\n const container = editorContainer.value.closest(\n \".form-demo\",\n ) as HTMLElement | null;\n if (container) {\n container.classList.add(\"editor-focused\");\n const containerWidth = container.scrollWidth;\n container.style.maxWidth = `${containerWidth}px`;\n }\n};\n\nconst handleEditorBlur = (): void => {\n if (!editorContainer.value) return;\n const container = editorContainer.value.closest(\n \".form-demo\",\n ) as HTMLElement | null;\n if (container) {\n container.classList.remove(\"editor-focused\");\n container.style.maxWidth = \"\";\n }\n};\n\nonMounted(() => {\n nextTick(() => {\n initializeEditor();\n });\n});\n\nonBeforeUnmount(() => {\n destroyEditor();\n});\n\ndefineExpose({\n initializeEditor,\n destroyEditor,\n setContent,\n getContent,\n handleEditorFocus,\n handleEditorBlur,\n editorInstance: readonly(editorInstance),\n isInitialized: readonly(isInitialized),\n});\n</script>\n\n<style scoped>\n/* CSS 变量 — 支持外部主题覆盖 */\n:root {\n --c-editor-toolbar-bg: #ffffff;\n --c-editor-toolbar-border: #e5e7eb;\n --c-editor-menu-color: #333333;\n --c-editor-menu-hover-bg: #f3f4f6;\n --c-editor-menu-hover-color: #333333;\n --c-editor-menu-active-bg: var(--c-primary, #2080f0);\n --c-editor-menu-active-color: #ffffff;\n --c-editor-container-bg: #ffffff;\n --c-editor-container-border: #e5e7eb;\n --c-editor-text-bg: #ffffff;\n --c-editor-text-color: #333333;\n --c-editor-text-focus-bg: #ffffff;\n --c-editor-text-focus-color: #333333;\n --c-editor-transition-duration: 0.3s;\n}\n\n/* 暗色主题 — 覆盖 CSS 变量 */\n.editor-dark {\n --c-editor-toolbar-bg: #1f2937;\n --c-editor-toolbar-border: #374151;\n --c-editor-menu-color: #e5e7eb;\n --c-editor-menu-hover-bg: #374151;\n --c-editor-menu-hover-color: #ffffff;\n --c-editor-container-bg: #111827;\n --c-editor-container-border: #374151;\n --c-editor-text-bg: #303033;\n --c-editor-text-color: #e5e7eb;\n --c-editor-text-focus-bg: #111827;\n --c-editor-text-focus-color: #e5e7eb;\n}\n\n.editor-dark :deep(.w-e-toolbar) {\n background-color: var(--c-editor-toolbar-bg) !important;\n border-color: var(--c-editor-toolbar-border) !important;\n}\n\n.editor-dark :deep(.w-e-toolbar .w-e-menu .w-e-menu-item) {\n color: var(--c-editor-menu-color) !important;\n}\n\n.editor-dark :deep(.w-e-toolbar .w-e-menu .w-e-menu-item:hover) {\n background-color: var(--c-editor-menu-hover-bg) !important;\n color: var(--c-editor-menu-hover-color) !important;\n}\n\n.editor-dark :deep(.w-e-toolbar .w-e-menu .w-e-menu-item.w-e-active) {\n background-color: var(--c-editor-menu-active-bg) !important;\n color: var(--c-editor-menu-active-color) !important;\n}\n\n.editor-dark :deep(.w-e-text-container) {\n background-color: var(--c-editor-container-bg) !important;\n border-color: var(--c-editor-container-border) !important;\n}\n\n.editor-dark :deep(.w-e-text-container .w-e-text) {\n background-color: var(--c-editor-text-bg) !important;\n color: var(--c-editor-text-color) !important;\n}\n\n.editor-dark :deep(.w-e-text-container .w-e-text:focus) {\n background-color: var(--c-editor-text-focus-bg) !important;\n color: var(--c-editor-text-focus-color) !important;\n}\n\n:deep(.w-e-toolbar),\n:deep(.w-e-text-container) {\n max-width: 100% !important;\n overflow-x: auto !important;\n box-sizing: border-box !important;\n}\n\n:deep(.w-e-text) {\n max-width: 100% !important;\n word-wrap: break-word !important;\n overflow-wrap: break-word !important;\n}\n\n:deep(.w-e-toolbar),\n:deep(.w-e-text-container),\n:deep(.w-e-text) {\n transition:\n background-color var(--c-editor-transition-duration) ease,\n border-color var(--c-editor-transition-duration) ease,\n color var(--c-editor-transition-duration) ease !important;\n}\n\n.editor-focused {\n overflow: hidden !important;\n max-width: 100% !important;\n}\n</style>\n","<!--\n * @Author: ChenYu ycyplus@gmail.com\n * @Date: 2025-06-01\n * @Description: 富文本编辑器组件(简化主题版)\n * @Migration: naive-ui-components 组件库迁移版本\n * Copyright (c) 2025 by CHENY, All Rights Reserved.\n-->\n<template>\n <div\n ref=\"editorContainer\"\n :id=\"editorId\"\n v-show=\"isInitialized\"\n class=\"w-full\"\n :class=\"{ 'editor-dark': isDark }\"\n @focusin=\"handleEditorFocus\"\n @focusout=\"handleEditorBlur\"\n ></div>\n</template>\n\n<script setup lang=\"ts\">\nimport {\n ref,\n computed,\n watch,\n nextTick,\n onMounted,\n onBeforeUnmount,\n readonly,\n} from \"vue\";\nimport E from \"wangeditor\";\n\ndefineOptions({ name: \"C_Editor\" });\n\ninterface Props {\n editorId: string;\n modelValue?: string;\n placeholder?: string;\n disabled?: boolean;\n readonly?: boolean;\n height?: number;\n theme?: \"light\" | \"dark\";\n}\n\ninterface Emits {\n (e: \"update:modelValue\", value: string): void;\n (e: \"editor-mounted\", editor: any): void;\n (e: \"editor-change\", html: string): void;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n modelValue: \"\",\n placeholder: \"\",\n disabled: false,\n readonly: false,\n height: 240,\n theme: \"light\",\n});\n\nconst emit = defineEmits<Emits>();\n\nconst editorContainer = ref<HTMLElement | null>(null);\nconst editorInstance = ref<any>(null);\nconst isInitialized = ref<boolean>(false);\n\nconst isDark = computed(() => props.theme === \"dark\");\n\nconst initializeEditor = (): void => {\n if (!editorContainer.value || isInitialized.value) return;\n\n try {\n const editor = new E(editorContainer.value);\n const editorConfig = editor.config as any;\n editorConfig.placeholder = props.placeholder;\n editorConfig.height = props.height - 50;\n\n editorConfig.onchange = (html: string) => {\n emit(\"update:modelValue\", html);\n emit(\"editor-change\", html);\n };\n\n editor.create();\n\n nextTick(() => {\n if (props.modelValue) {\n editor.txt.html(props.modelValue);\n }\n if (props.readonly) {\n editor.disable();\n }\n editorInstance.value = editor;\n isInitialized.value = true;\n emit(\"editor-mounted\", editor);\n });\n } catch (error) {\n console.error(`[C_Editor] 编辑器初始化失败: ${props.editorId}`, error);\n }\n};\n\nconst destroyEditor = (): void => {\n if (editorInstance.value && isInitialized.value) {\n try {\n editorInstance.value.destroy();\n editorInstance.value = null;\n isInitialized.value = false;\n } catch (error) {\n console.error(`[C_Editor] 编辑器销毁失败: ${props.editorId}`, error);\n }\n }\n};\n\nconst setContent = (html: string): void => {\n if (editorInstance.value && isInitialized.value) {\n try {\n editorInstance.value.txt.html(html);\n } catch (error) {\n console.warn(`[C_Editor] 设置编辑器内容失败: ${props.editorId}`, error);\n }\n }\n};\n\nconst getContent = (): string => {\n if (editorInstance.value && isInitialized.value) {\n try {\n return editorInstance.value.txt.html();\n } catch (error) {\n console.warn(`[C_Editor] 获取编辑器内容失败: ${props.editorId}`, error);\n return \"\";\n }\n }\n return \"\";\n};\n\nwatch(\n () => props.modelValue,\n (newValue) => {\n if (editorInstance.value && isInitialized.value) {\n const currentContent = editorInstance.value.txt.html();\n if (currentContent !== newValue) {\n editorInstance.value.txt.html(newValue || \"\");\n }\n }\n },\n);\n\nwatch(\n () => props.disabled,\n (disabled) => {\n if (editorInstance.value && isInitialized.value) {\n try {\n if (disabled) editorInstance.value.disable();\n else editorInstance.value.enable();\n } catch (error) {\n console.warn(`[C_Editor] 设置编辑器状态失败`, error);\n }\n }\n },\n);\n\nwatch(\n () => props.readonly,\n (readonlyVal) => {\n if (editorInstance.value && isInitialized.value) {\n try {\n if (readonlyVal) editorInstance.value.disable();\n else editorInstance.value.enable();\n } catch (error) {\n console.warn(`[C_Editor] 设置编辑器只读状态失败`, error);\n }\n }\n },\n);\n\nconst handleEditorFocus = (): void => {\n if (!editorContainer.value) return;\n const container = editorContainer.value.closest(\n \".form-demo\",\n ) as HTMLElement | null;\n if (container) {\n container.classList.add(\"editor-focused\");\n const containerWidth = container.scrollWidth;\n container.style.maxWidth = `${containerWidth}px`;\n }\n};\n\nconst handleEditorBlur = (): void => {\n if (!editorContainer.value) return;\n const container = editorContainer.value.closest(\n \".form-demo\",\n ) as HTMLElement | null;\n if (container) {\n container.classList.remove(\"editor-focused\");\n container.style.maxWidth = \"\";\n }\n};\n\nonMounted(() => {\n nextTick(() => {\n initializeEditor();\n });\n});\n\nonBeforeUnmount(() => {\n destroyEditor();\n});\n\ndefineExpose({\n initializeEditor,\n destroyEditor,\n setContent,\n getContent,\n handleEditorFocus,\n handleEditorBlur,\n editorInstance: readonly(editorInstance),\n isInitialized: readonly(isInitialized),\n});\n</script>\n\n<style scoped>\n/* CSS 变量 — 支持外部主题覆盖 */\n:root {\n --c-editor-toolbar-bg: #ffffff;\n --c-editor-toolbar-border: #e5e7eb;\n --c-editor-menu-color: #333333;\n --c-editor-menu-hover-bg: #f3f4f6;\n --c-editor-menu-hover-color: #333333;\n --c-editor-menu-active-bg: var(--c-primary, #2080f0);\n --c-editor-menu-active-color: #ffffff;\n --c-editor-container-bg: #ffffff;\n --c-editor-container-border: #e5e7eb;\n --c-editor-text-bg: #ffffff;\n --c-editor-text-color: #333333;\n --c-editor-text-focus-bg: #ffffff;\n --c-editor-text-focus-color: #333333;\n --c-editor-transition-duration: 0.3s;\n}\n\n/* 暗色主题 — 覆盖 CSS 变量 */\n.editor-dark {\n --c-editor-toolbar-bg: #1f2937;\n --c-editor-toolbar-border: #374151;\n --c-editor-menu-color: #e5e7eb;\n --c-editor-menu-hover-bg: #374151;\n --c-editor-menu-hover-color: #ffffff;\n --c-editor-container-bg: #111827;\n --c-editor-container-border: #374151;\n --c-editor-text-bg: #303033;\n --c-editor-text-color: #e5e7eb;\n --c-editor-text-focus-bg: #111827;\n --c-editor-text-focus-color: #e5e7eb;\n}\n\n.editor-dark :deep(.w-e-toolbar) {\n background-color: var(--c-editor-toolbar-bg) !important;\n border-color: var(--c-editor-toolbar-border) !important;\n}\n\n.editor-dark :deep(.w-e-toolbar .w-e-menu .w-e-menu-item) {\n color: var(--c-editor-menu-color) !important;\n}\n\n.editor-dark :deep(.w-e-toolbar .w-e-menu .w-e-menu-item:hover) {\n background-color: var(--c-editor-menu-hover-bg) !important;\n color: var(--c-editor-menu-hover-color) !important;\n}\n\n.editor-dark :deep(.w-e-toolbar .w-e-menu .w-e-menu-item.w-e-active) {\n background-color: var(--c-editor-menu-active-bg) !important;\n color: var(--c-editor-menu-active-color) !important;\n}\n\n.editor-dark :deep(.w-e-text-container) {\n background-color: var(--c-editor-container-bg) !important;\n border-color: var(--c-editor-container-border) !important;\n}\n\n.editor-dark :deep(.w-e-text-container .w-e-text) {\n background-color: var(--c-editor-text-bg) !important;\n color: var(--c-editor-text-color) !important;\n}\n\n.editor-dark :deep(.w-e-text-container .w-e-text:focus) {\n background-color: var(--c-editor-text-focus-bg) !important;\n color: var(--c-editor-text-focus-color) !important;\n}\n\n:deep(.w-e-toolbar),\n:deep(.w-e-text-container) {\n max-width: 100% !important;\n overflow-x: auto !important;\n box-sizing: border-box !important;\n}\n\n:deep(.w-e-text) {\n max-width: 100% !important;\n word-wrap: break-word !important;\n overflow-wrap: break-word !important;\n}\n\n:deep(.w-e-toolbar),\n:deep(.w-e-text-container),\n:deep(.w-e-text) {\n transition:\n background-color var(--c-editor-transition-duration) ease,\n border-color var(--c-editor-transition-duration) ease,\n color var(--c-editor-transition-duration) ease !important;\n}\n\n.editor-focused {\n overflow: hidden !important;\n max-width: 100% !important;\n}\n</style>\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"C_FilePreview-Bs_omgJS.css","names":[],"sources":["../src/components/C_FilePreview/components/PdfViewer/index.vue?vue&type=style&index=0&scoped=6ef071db&lang.scss","../src/components/C_FilePreview/components/WordViewer/index.vue?vue&type=style&index=0&scoped=31f606d3&lang.scss","../src/components/C_FilePreview/components/ExcelViewer/index.vue?vue&type=style&index=0&scoped=5569b81f&lang.scss","../src/components/C_FilePreview/index.vue?vue&type=style&index=0&scoped=7c7c652b&lang.scss"],"sourcesContent":["/* unplugin-vue-components disabled */.file-container[data-v-6ef071db] {\n display: flex;\n flex-direction: column;\n height: 100%;\n}\n.file-container .file-toolbar[data-v-6ef071db] {\n padding: 12px 16px;\n border-bottom: 1px solid var(--c-border, #e0e0e0);\n background-color: var(--c-bg-card, #f9f9f9);\n flex-shrink: 0;\n z-index: 8;\n position: relative;\n}\n.file-container .file-viewer[data-v-6ef071db] {\n flex: 1;\n min-height: 300px;\n}","/* unplugin-vue-components disabled */.file-container[data-v-31f606d3] {\n display: flex;\n flex-direction: column;\n height: 100%;\n}\n.file-container .file-toolbar[data-v-31f606d3] {\n padding: 12px 16px;\n border-bottom: 1px solid var(--c-border, #e0e0e0);\n background-color: var(--c-bg-card, #f9f9f9);\n flex-shrink: 0;\n z-index: 8;\n position: relative;\n}\n.word-layout[data-v-31f606d3] {\n display: flex;\n flex-direction: column;\n height: 100%;\n}\n.word-layout .word-main[data-v-31f606d3] {\n flex: 1;\n display: flex;\n overflow: hidden;\n}\n.word-layout .word-main .word-outline[data-v-31f606d3] {\n width: 280px;\n border-right: 1px solid var(--c-border, #e0e0e0);\n background-color: var(--c-bg-card, #f9f9f9);\n}\n.word-layout .word-main .word-outline .outline-header[data-v-31f606d3] {\n padding: 16px;\n border-bottom: 1px solid var(--c-border, #e0e0e0);\n}\n.word-layout .word-main .word-outline .outline-content[data-v-31f606d3] {\n padding: 8px;\n overflow-y: auto;\n}\n.word-layout .word-main .word-outline .outline-content .outline-item[data-v-31f606d3] {\n padding: 8px 12px;\n cursor: pointer;\n border-radius: 4px;\n font-size: 14px;\n color: var(--c-text-1, #333);\n}\n.word-layout .word-main .word-outline .outline-content .outline-item[data-v-31f606d3]:hover {\n background-color: #e6f3ff;\n}\n.word-layout .word-main .word-outline .outline-content .outline-item.level-1[data-v-31f606d3] {\n padding-left: 12px;\n font-weight: 600;\n}\n.word-layout .word-main .word-outline .outline-content .outline-item.level-2[data-v-31f606d3] {\n padding-left: 24px;\n}\n.word-layout .word-main .word-outline .outline-content .outline-item.level-3[data-v-31f606d3], .word-layout .word-main .word-outline .outline-content .outline-item.level-4[data-v-31f606d3] {\n padding-left: 36px;\n font-size: 13px;\n}\n.word-layout .word-main .word-outline .outline-content .outline-item.level-4[data-v-31f606d3] {\n padding-left: 48px;\n}\n.word-layout .word-main .word-content[data-v-31f606d3] {\n flex: 1;\n padding: 24px;\n overflow: auto;\n}\n.word-layout .word-main .word-content .word-document[data-v-31f606d3] {\n max-width: 800px;\n margin: 0 auto;\n background: var(--c-bg-card, white);\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\n padding: 40px;\n}\n.word-layout .word-main .word-content .word-document[data-v-31f606d3] h1 {\n margin: 24px 0 16px 0;\n font-weight: bold;\n}\n.word-layout .word-main .word-content .word-document[data-v-31f606d3] h1 {\n font-size: 1.8rem;\n color: var(--c-text-1, #333);\n border-bottom: 2px solid var(--c-border, #e0e0e0);\n padding-bottom: 8px;\n}\n.word-layout .word-main .word-content .word-document[data-v-31f606d3] h2 {\n font-size: 1.5rem;\n color: var(--c-text-1, #444);\n margin: 20px 0 12px 0;\n}\n.word-layout .word-main .word-content .word-document[data-v-31f606d3] h3 {\n font-size: 1.25rem;\n color: var(--c-text-2, #555);\n margin: 16px 0 8px 0;\n}\n.word-layout .word-main .word-content .word-document[data-v-31f606d3] p {\n margin-bottom: 12px;\n line-height: 1.8;\n color: var(--c-text-1, #333);\n}\n.word-layout .word-main .word-content .word-document[data-v-31f606d3] ul {\n margin: 12px 0;\n padding-left: 24px;\n}\n.word-layout .word-main .word-content .word-document[data-v-31f606d3] li {\n margin-bottom: 6px;\n line-height: 1.6;\n}\n.word-layout .word-main .word-content .word-document[data-v-31f606d3] table {\n width: 100%;\n border-collapse: collapse;\n margin: 16px 0;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n.word-layout .word-main .word-content .word-document[data-v-31f606d3] th {\n border: 1px solid #d0d0d0;\n padding: 12px;\n text-align: left;\n}\n.word-layout .word-main .word-content .word-document[data-v-31f606d3] th {\n background-color: var(--c-bg-card, #f5f5f5);\n font-weight: bold;\n}","/* unplugin-vue-components disabled */.file-container[data-v-5569b81f] {\n display: flex;\n flex-direction: column;\n height: 100%;\n}\n.file-container .file-toolbar[data-v-5569b81f] {\n padding: 12px 16px;\n border-bottom: 1px solid var(--c-border, #e0e0e0);\n background-color: var(--c-bg-card, #f9f9f9);\n flex-shrink: 0;\n z-index: 8;\n position: relative;\n}\n.excel-container[data-v-5569b81f] {\n overflow: visible;\n}\n.excel-container .excel-viewer[data-v-5569b81f] {\n display: flex;\n flex-direction: column;\n height: 100%;\n overflow: visible;\n}\n.excel-container .excel-viewer .excel-info[data-v-5569b81f] {\n padding: 8px 16px;\n background-color: var(--c-bg-card, #f9f9f9);\n border-bottom: 1px solid var(--c-border, #e0e0e0);\n flex-shrink: 0;\n z-index: 7;\n position: relative;\n}\n.excel-container .excel-viewer .excel-table-container[data-v-5569b81f] {\n flex: 1;\n display: flex;\n flex-direction: column;\n overflow: visible;\n min-height: 0;\n}\n.excel-container .excel-viewer .excel-table-container .excel-table-wrapper[data-v-5569b81f] {\n flex: 1;\n overflow: auto;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\n border-radius: 4px;\n}\n.excel-container .excel-viewer .excel-table-container .excel-table-wrapper.simple-mode .excel-table[data-v-5569b81f] {\n font-size: 12px;\n}\n.excel-container .excel-viewer .excel-table-container .excel-table-wrapper.simple-mode .excel-table .excel-header[data-v-5569b81f] {\n padding: 6px 8px;\n background: #f8f9fa;\n}\n.excel-container .excel-viewer .excel-table-container .excel-table-wrapper.simple-mode .excel-table .excel-header .header-content .column-letter[data-v-5569b81f] {\n display: none;\n}\n.excel-container .excel-viewer .excel-table-container .excel-table-wrapper.simple-mode .excel-table .excel-header .header-content .column-title[data-v-5569b81f] {\n font-size: 11px;\n}\n.excel-container .excel-viewer .excel-table-container .excel-table-wrapper.simple-mode .excel-table .excel-row[data-v-5569b81f]:nth-child(even) {\n background-color: #fefefe;\n}\n.excel-container .excel-viewer .excel-table-container .excel-table-wrapper.simple-mode .excel-table .excel-cell[data-v-5569b81f] {\n padding: 4px 8px;\n font-size: 12px;\n}\n.excel-container .excel-viewer .excel-table-container .excel-table-wrapper.simple-mode .excel-table .excel-cell.merged-cell[data-v-5569b81f] {\n border: 1px solid #1976d2 !important;\n}\n.excel-container .excel-viewer .excel-table-container .excel-table-wrapper.simple-mode .excel-table .excel-cell.merged-cell[data-v-5569b81f]::after {\n display: none;\n}\n.excel-container .excel-viewer .excel-table-container .excel-table[data-v-5569b81f] {\n width: 100%;\n border-collapse: separate;\n border-spacing: 0;\n font-size: 13px;\n min-width: 100%;\n}\n.excel-container .excel-viewer .excel-table-container .excel-table .row-number[data-v-5569b81f] {\n background: linear-gradient(135deg, #f0f0f0 0%, #e8e8e8 100%);\n text-align: center;\n min-width: 30px;\n width: 30px;\n padding: 2px 4px;\n font-size: 11px;\n font-weight: bold;\n border: 1px solid #d0d0d0;\n color: #666;\n position: sticky;\n left: 0;\n z-index: 10;\n}\n.excel-container .excel-viewer .excel-table-container .excel-table .excel-header[data-v-5569b81f] {\n background: linear-gradient(135deg, #f5f5f5 0%, #e8e8e8 100%);\n padding: 8px 12px;\n border: 1px solid #c0c0c0;\n font-weight: bold;\n position: sticky;\n top: 0;\n z-index: 5;\n}\n.excel-container .excel-viewer .excel-table-container .excel-table .excel-header .header-content[data-v-5569b81f] {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 2px;\n}\n.excel-container .excel-viewer .excel-table-container .excel-table .excel-header .header-content .column-letter[data-v-5569b81f] {\n background-color: var(--c-primary, #1976d2);\n color: white;\n padding: 2px 6px;\n border-radius: 3px;\n font-size: 10px;\n font-weight: normal;\n}\n.excel-container .excel-viewer .excel-table-container .excel-table .excel-header .header-content .column-title[data-v-5569b81f] {\n font-size: 12px;\n font-weight: bold;\n text-align: center;\n word-break: break-all;\n}\n.excel-container .excel-viewer .excel-table-container .excel-table .excel-row[data-v-5569b81f]:nth-child(even) {\n background-color: #fafafa;\n}\n.excel-container .excel-viewer .excel-table-container .excel-table .excel-row[data-v-5569b81f]:hover {\n background-color: #e6f3ff;\n}\n.excel-container .excel-viewer .excel-table-container .excel-table .excel-cell[data-v-5569b81f] {\n padding: 8px 12px;\n border: 1px solid #d0d0d0;\n vertical-align: middle;\n word-wrap: break-word;\n word-break: break-all;\n min-height: 24px;\n line-height: 1.4;\n position: relative;\n}\n.excel-container .excel-viewer .excel-table-container .excel-table .excel-cell.cell-number[data-v-5569b81f] {\n text-align: right;\n font-family: \"Courier New\", monospace;\n}\n.excel-container .excel-viewer .excel-table-container .excel-table .excel-cell.cell-gantt[data-v-5569b81f] {\n text-align: center;\n font-family: monospace;\n font-size: 14px;\n font-weight: bold;\n background-color: #f0f0f0;\n color: var(--c-text-1, #333);\n}\n.excel-container .excel-viewer .excel-table-container .excel-table .excel-cell.cell-date[data-v-5569b81f] {\n color: var(--c-primary, #1976d2);\n}\n.excel-container .excel-viewer .excel-table-container .excel-table .excel-cell.cell-boolean[data-v-5569b81f] {\n text-align: center;\n font-weight: bold;\n}\n.excel-container .excel-viewer .excel-table-container .excel-table .excel-cell.cell-long[data-v-5569b81f] {\n max-width: 200px;\n white-space: pre-wrap;\n}\n.excel-container .excel-viewer .excel-table-container .excel-table .excel-cell.cell-empty[data-v-5569b81f] {\n background-color: #fafafa;\n}\n.excel-container .excel-viewer .excel-table-container .excel-table .excel-cell.merged-cell[data-v-5569b81f] {\n background: linear-gradient(135deg, #f0f8ff 0%, #e3f2fd 100%) !important;\n border: 2px solid var(--c-primary, #1976d2) !important;\n font-weight: bold;\n text-align: center;\n color: var(--c-primary, #1976d2);\n}\n.excel-container .excel-viewer .excel-table-container .excel-table .excel-cell.merged-cell[data-v-5569b81f]::before {\n content: \"\";\n position: absolute;\n top: 3px;\n left: 3px;\n right: 3px;\n bottom: 3px;\n background: rgba(25, 118, 210, 0.08);\n border-radius: 2px;\n pointer-events: none;\n}\n.excel-container .excel-viewer .excel-table-container .excel-table .excel-cell.merged-cell[data-v-5569b81f]::after {\n content: \"📎\";\n position: absolute;\n top: 2px;\n right: 4px;\n font-size: 10px;\n opacity: 0.6;\n}\n.excel-container .excel-viewer .excel-table-container .excel-table .excel-cell.compact-cell[data-v-5569b81f] {\n padding: 4px 8px;\n font-size: 12px;\n}\n.excel-container .excel-viewer .excel-table-container .excel-table .excel-cell.compact-cell.merged-cell[data-v-5569b81f] {\n background: linear-gradient(135deg, #f0f8ff 0%, #e3f2fd 100%) !important;\n border: 1px solid var(--c-primary, #1976d2) !important;\n font-weight: bold;\n text-align: center;\n color: var(--c-primary, #1976d2);\n}\n.excel-container .excel-viewer .excel-table-container .excel-table .excel-cell.compact-cell.merged-cell[data-v-5569b81f]::before {\n top: 2px;\n left: 2px;\n right: 2px;\n bottom: 2px;\n background: rgba(25, 118, 210, 0.05);\n}\n.excel-container .excel-viewer .excel-table-container .excel-table .excel-cell.compact-cell.merged-cell[data-v-5569b81f]::after {\n display: none;\n}\n.excel-container .excel-viewer .excel-table-container .excel-empty[data-v-5569b81f] {\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n min-height: 200px;\n}\n.excel-container .excel-viewer .excel-table-container .excel-pagination[data-v-5569b81f] {\n padding: 20px 16px;\n border-top: 1px solid var(--c-border, #e0e0e0);\n background-color: var(--c-bg-card, #f9f9f9);\n display: flex;\n justify-content: center;\n flex-shrink: 0;\n z-index: 1000;\n position: relative;\n overflow: visible;\n}\n.excel-container .excel-viewer .excel-table-container .excel-pagination[data-v-5569b81f] .n-pagination {\n z-index: 1001;\n position: relative;\n}\n.excel-container .excel-viewer .excel-table-container .excel-pagination[data-v-5569b81f] .n-pagination-size-picker {\n z-index: 1002;\n position: relative;\n}\n.excel-container .excel-viewer .excel-table-container .excel-pagination[data-v-5569b81f] .n-pagination-size-picker .n-base-selection {\n z-index: 1003;\n}\n.excel-container .excel-viewer .excel-table-container .excel-pagination[data-v-5569b81f] .n-pagination-size-picker .n-base-selection-popover {\n z-index: 1004 !important;\n}\n.excel-container .excel-viewer .excel-table-container .excel-pagination[data-v-5569b81f] .n-popover {\n z-index: 1005 !important;\n}","/* unplugin-vue-components disabled */.c-file-preview-wrapper[data-v-7c7c652b] {\n width: 100%;\n}\n.c-file-preview-wrapper .file-info-card .file-info[data-v-7c7c652b] {\n display: flex;\n align-items: center;\n gap: 16px;\n padding: 16px;\n border: 1px solid var(--c-border, #e0e0e0);\n border-radius: 12px;\n background: var(--c-bg-card, white);\n transition: var(--c-transition, 0.2s ease);\n cursor: pointer;\n}\n.c-file-preview-wrapper .file-info-card .file-info[data-v-7c7c652b]:hover {\n border-color: var(--c-primary, #40a9ff);\n box-shadow: 0 4px 12px rgba(64, 169, 255, 0.15);\n transform: translateY(-1px);\n}\n.c-file-preview-wrapper .file-info-card .file-info .file-icon[data-v-7c7c652b] {\n flex-shrink: 0;\n width: 56px;\n height: 56px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);\n border-radius: 12px;\n border: 1px solid #dee2e6;\n}\n.c-file-preview-wrapper .file-info-card .file-info .file-details[data-v-7c7c652b] {\n flex: 1;\n min-width: 0;\n}\n.c-file-preview-wrapper .file-info-card .file-info .file-details .file-name[data-v-7c7c652b] {\n display: flex;\n align-items: center;\n gap: 12px;\n margin-bottom: 6px;\n font-weight: 600;\n font-size: 16px;\n color: var(--c-text-1, #1f2937);\n}\n.c-file-preview-wrapper .file-info-card .file-info .file-details .file-meta[data-v-7c7c652b] {\n display: flex;\n gap: 16px;\n font-size: 13px;\n color: var(--c-text-2, #6b7280);\n}\n.c-file-preview-wrapper .file-info-card .file-info .file-details .file-meta .file-size[data-v-7c7c652b] {\n font-weight: 500;\n color: var(--c-text-1, #374151);\n}\n.c-file-preview-wrapper .file-info-card .file-info .file-actions[data-v-7c7c652b] {\n flex-shrink: 0;\n display: flex;\n gap: 8px;\n}\n.modal-container[data-v-7c7c652b] {\n background: var(--c-bg-card, white);\n border-radius: 8px;\n box-shadow: 0 20px 40px rgba(0, 0, 0, 0.15);\n display: flex;\n flex-direction: column;\n width: 100%;\n height: 100%;\n overflow: visible;\n}\n.modal-container .modal-header[data-v-7c7c652b] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 16px 20px;\n background: var(--c-bg, #fafafa);\n border-bottom: 1px solid var(--c-border, #e0e0e0);\n flex-shrink: 0;\n z-index: 10;\n position: relative;\n}\n.modal-container .modal-header .modal-title[data-v-7c7c652b] {\n display: flex;\n align-items: center;\n gap: 8px;\n font-weight: 600;\n font-size: 16px;\n color: var(--c-text-1, #333);\n}\n.modal-container .modal-header .modal-title span[data-v-7c7c652b] {\n max-width: 400px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.modal-container .modal-header .modal-actions[data-v-7c7c652b] {\n display: flex;\n gap: 8px;\n align-items: center;\n}\n.modal-container .modal-content[data-v-7c7c652b] {\n flex: 1;\n display: flex;\n flex-direction: column;\n overflow: visible;\n min-height: 0;\n}\n.modal-container .preview-header[data-v-7c7c652b] {\n padding: 16px;\n border-bottom: 1px solid var(--c-border, #e0e0e0);\n background-color: var(--c-bg-card, #f9f9f9);\n flex-shrink: 0;\n z-index: 9;\n position: relative;\n}\n.modal-container .preview-content[data-v-7c7c652b] {\n flex: 1;\n overflow: auto;\n min-height: 0;\n position: relative;\n}\n.modal-container .preview-content .status-container[data-v-7c7c652b] {\n height: 300px;\n display: flex;\n align-items: center;\n justify-content: center;\n}"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AChBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;ACvHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AClPA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"C_FilePreview-DbwoyF2j.css","names":[],"sources":["../src/components/C_FilePreview/components/PdfViewer/index.vue?vue&type=style&index=0&scoped=6ef071db&lang.scss","../src/components/C_FilePreview/components/WordViewer/index.vue?vue&type=style&index=0&scoped=31f606d3&lang.scss","../src/components/C_FilePreview/components/ExcelViewer/index.vue?vue&type=style&index=0&scoped=5569b81f&lang.scss","../src/components/C_FilePreview/index.vue?vue&type=style&index=0&scoped=7c7c652b&lang.scss"],"sourcesContent":["/* unplugin-vue-components disabled */.file-container[data-v-6ef071db] {\n display: flex;\n flex-direction: column;\n height: 100%;\n}\n.file-container .file-toolbar[data-v-6ef071db] {\n padding: 12px 16px;\n border-bottom: 1px solid var(--c-border, #e0e0e0);\n background-color: var(--c-bg-card, #f9f9f9);\n flex-shrink: 0;\n z-index: 8;\n position: relative;\n}\n.file-container .file-viewer[data-v-6ef071db] {\n flex: 1;\n min-height: 300px;\n}","/* unplugin-vue-components disabled */.file-container[data-v-31f606d3] {\n display: flex;\n flex-direction: column;\n height: 100%;\n}\n.file-container .file-toolbar[data-v-31f606d3] {\n padding: 12px 16px;\n border-bottom: 1px solid var(--c-border, #e0e0e0);\n background-color: var(--c-bg-card, #f9f9f9);\n flex-shrink: 0;\n z-index: 8;\n position: relative;\n}\n.word-layout[data-v-31f606d3] {\n display: flex;\n flex-direction: column;\n height: 100%;\n}\n.word-layout .word-main[data-v-31f606d3] {\n flex: 1;\n display: flex;\n overflow: hidden;\n}\n.word-layout .word-main .word-outline[data-v-31f606d3] {\n width: 280px;\n border-right: 1px solid var(--c-border, #e0e0e0);\n background-color: var(--c-bg-card, #f9f9f9);\n}\n.word-layout .word-main .word-outline .outline-header[data-v-31f606d3] {\n padding: 16px;\n border-bottom: 1px solid var(--c-border, #e0e0e0);\n}\n.word-layout .word-main .word-outline .outline-content[data-v-31f606d3] {\n padding: 8px;\n overflow-y: auto;\n}\n.word-layout .word-main .word-outline .outline-content .outline-item[data-v-31f606d3] {\n padding: 8px 12px;\n cursor: pointer;\n border-radius: 4px;\n font-size: 14px;\n color: var(--c-text-1, #333);\n}\n.word-layout .word-main .word-outline .outline-content .outline-item[data-v-31f606d3]:hover {\n background-color: #e6f3ff;\n}\n.word-layout .word-main .word-outline .outline-content .outline-item.level-1[data-v-31f606d3] {\n padding-left: 12px;\n font-weight: 600;\n}\n.word-layout .word-main .word-outline .outline-content .outline-item.level-2[data-v-31f606d3] {\n padding-left: 24px;\n}\n.word-layout .word-main .word-outline .outline-content .outline-item.level-3[data-v-31f606d3], .word-layout .word-main .word-outline .outline-content .outline-item.level-4[data-v-31f606d3] {\n padding-left: 36px;\n font-size: 13px;\n}\n.word-layout .word-main .word-outline .outline-content .outline-item.level-4[data-v-31f606d3] {\n padding-left: 48px;\n}\n.word-layout .word-main .word-content[data-v-31f606d3] {\n flex: 1;\n padding: 24px;\n overflow: auto;\n}\n.word-layout .word-main .word-content .word-document[data-v-31f606d3] {\n max-width: 800px;\n margin: 0 auto;\n background: var(--c-bg-card, white);\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\n padding: 40px;\n}\n.word-layout .word-main .word-content .word-document[data-v-31f606d3] h1 {\n margin: 24px 0 16px 0;\n font-weight: bold;\n}\n.word-layout .word-main .word-content .word-document[data-v-31f606d3] h1 {\n font-size: 1.8rem;\n color: var(--c-text-1, #333);\n border-bottom: 2px solid var(--c-border, #e0e0e0);\n padding-bottom: 8px;\n}\n.word-layout .word-main .word-content .word-document[data-v-31f606d3] h2 {\n font-size: 1.5rem;\n color: var(--c-text-1, #444);\n margin: 20px 0 12px 0;\n}\n.word-layout .word-main .word-content .word-document[data-v-31f606d3] h3 {\n font-size: 1.25rem;\n color: var(--c-text-2, #555);\n margin: 16px 0 8px 0;\n}\n.word-layout .word-main .word-content .word-document[data-v-31f606d3] p {\n margin-bottom: 12px;\n line-height: 1.8;\n color: var(--c-text-1, #333);\n}\n.word-layout .word-main .word-content .word-document[data-v-31f606d3] ul {\n margin: 12px 0;\n padding-left: 24px;\n}\n.word-layout .word-main .word-content .word-document[data-v-31f606d3] li {\n margin-bottom: 6px;\n line-height: 1.6;\n}\n.word-layout .word-main .word-content .word-document[data-v-31f606d3] table {\n width: 100%;\n border-collapse: collapse;\n margin: 16px 0;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n.word-layout .word-main .word-content .word-document[data-v-31f606d3] th {\n border: 1px solid #d0d0d0;\n padding: 12px;\n text-align: left;\n}\n.word-layout .word-main .word-content .word-document[data-v-31f606d3] th {\n background-color: var(--c-bg-card, #f5f5f5);\n font-weight: bold;\n}","/* unplugin-vue-components disabled */.file-container[data-v-5569b81f] {\n display: flex;\n flex-direction: column;\n height: 100%;\n}\n.file-container .file-toolbar[data-v-5569b81f] {\n padding: 12px 16px;\n border-bottom: 1px solid var(--c-border, #e0e0e0);\n background-color: var(--c-bg-card, #f9f9f9);\n flex-shrink: 0;\n z-index: 8;\n position: relative;\n}\n.excel-container[data-v-5569b81f] {\n overflow: visible;\n}\n.excel-container .excel-viewer[data-v-5569b81f] {\n display: flex;\n flex-direction: column;\n height: 100%;\n overflow: visible;\n}\n.excel-container .excel-viewer .excel-info[data-v-5569b81f] {\n padding: 8px 16px;\n background-color: var(--c-bg-card, #f9f9f9);\n border-bottom: 1px solid var(--c-border, #e0e0e0);\n flex-shrink: 0;\n z-index: 7;\n position: relative;\n}\n.excel-container .excel-viewer .excel-table-container[data-v-5569b81f] {\n flex: 1;\n display: flex;\n flex-direction: column;\n overflow: visible;\n min-height: 0;\n}\n.excel-container .excel-viewer .excel-table-container .excel-table-wrapper[data-v-5569b81f] {\n flex: 1;\n overflow: auto;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\n border-radius: 4px;\n}\n.excel-container .excel-viewer .excel-table-container .excel-table-wrapper.simple-mode .excel-table[data-v-5569b81f] {\n font-size: 12px;\n}\n.excel-container .excel-viewer .excel-table-container .excel-table-wrapper.simple-mode .excel-table .excel-header[data-v-5569b81f] {\n padding: 6px 8px;\n background: #f8f9fa;\n}\n.excel-container .excel-viewer .excel-table-container .excel-table-wrapper.simple-mode .excel-table .excel-header .header-content .column-letter[data-v-5569b81f] {\n display: none;\n}\n.excel-container .excel-viewer .excel-table-container .excel-table-wrapper.simple-mode .excel-table .excel-header .header-content .column-title[data-v-5569b81f] {\n font-size: 11px;\n}\n.excel-container .excel-viewer .excel-table-container .excel-table-wrapper.simple-mode .excel-table .excel-row[data-v-5569b81f]:nth-child(even) {\n background-color: #fefefe;\n}\n.excel-container .excel-viewer .excel-table-container .excel-table-wrapper.simple-mode .excel-table .excel-cell[data-v-5569b81f] {\n padding: 4px 8px;\n font-size: 12px;\n}\n.excel-container .excel-viewer .excel-table-container .excel-table-wrapper.simple-mode .excel-table .excel-cell.merged-cell[data-v-5569b81f] {\n border: 1px solid #1976d2 !important;\n}\n.excel-container .excel-viewer .excel-table-container .excel-table-wrapper.simple-mode .excel-table .excel-cell.merged-cell[data-v-5569b81f]::after {\n display: none;\n}\n.excel-container .excel-viewer .excel-table-container .excel-table[data-v-5569b81f] {\n width: 100%;\n border-collapse: separate;\n border-spacing: 0;\n font-size: 13px;\n min-width: 100%;\n}\n.excel-container .excel-viewer .excel-table-container .excel-table .row-number[data-v-5569b81f] {\n background: linear-gradient(135deg, #f0f0f0 0%, #e8e8e8 100%);\n text-align: center;\n min-width: 30px;\n width: 30px;\n padding: 2px 4px;\n font-size: 11px;\n font-weight: bold;\n border: 1px solid #d0d0d0;\n color: #666;\n position: sticky;\n left: 0;\n z-index: 10;\n}\n.excel-container .excel-viewer .excel-table-container .excel-table .excel-header[data-v-5569b81f] {\n background: linear-gradient(135deg, #f5f5f5 0%, #e8e8e8 100%);\n padding: 8px 12px;\n border: 1px solid #c0c0c0;\n font-weight: bold;\n position: sticky;\n top: 0;\n z-index: 5;\n}\n.excel-container .excel-viewer .excel-table-container .excel-table .excel-header .header-content[data-v-5569b81f] {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 2px;\n}\n.excel-container .excel-viewer .excel-table-container .excel-table .excel-header .header-content .column-letter[data-v-5569b81f] {\n background-color: var(--c-primary, #1976d2);\n color: white;\n padding: 2px 6px;\n border-radius: 3px;\n font-size: 10px;\n font-weight: normal;\n}\n.excel-container .excel-viewer .excel-table-container .excel-table .excel-header .header-content .column-title[data-v-5569b81f] {\n font-size: 12px;\n font-weight: bold;\n text-align: center;\n word-break: break-all;\n}\n.excel-container .excel-viewer .excel-table-container .excel-table .excel-row[data-v-5569b81f]:nth-child(even) {\n background-color: #fafafa;\n}\n.excel-container .excel-viewer .excel-table-container .excel-table .excel-row[data-v-5569b81f]:hover {\n background-color: #e6f3ff;\n}\n.excel-container .excel-viewer .excel-table-container .excel-table .excel-cell[data-v-5569b81f] {\n padding: 8px 12px;\n border: 1px solid #d0d0d0;\n vertical-align: middle;\n word-wrap: break-word;\n word-break: break-all;\n min-height: 24px;\n line-height: 1.4;\n position: relative;\n}\n.excel-container .excel-viewer .excel-table-container .excel-table .excel-cell.cell-number[data-v-5569b81f] {\n text-align: right;\n font-family: \"Courier New\", monospace;\n}\n.excel-container .excel-viewer .excel-table-container .excel-table .excel-cell.cell-gantt[data-v-5569b81f] {\n text-align: center;\n font-family: monospace;\n font-size: 14px;\n font-weight: bold;\n background-color: #f0f0f0;\n color: var(--c-text-1, #333);\n}\n.excel-container .excel-viewer .excel-table-container .excel-table .excel-cell.cell-date[data-v-5569b81f] {\n color: var(--c-primary, #1976d2);\n}\n.excel-container .excel-viewer .excel-table-container .excel-table .excel-cell.cell-boolean[data-v-5569b81f] {\n text-align: center;\n font-weight: bold;\n}\n.excel-container .excel-viewer .excel-table-container .excel-table .excel-cell.cell-long[data-v-5569b81f] {\n max-width: 200px;\n white-space: pre-wrap;\n}\n.excel-container .excel-viewer .excel-table-container .excel-table .excel-cell.cell-empty[data-v-5569b81f] {\n background-color: #fafafa;\n}\n.excel-container .excel-viewer .excel-table-container .excel-table .excel-cell.merged-cell[data-v-5569b81f] {\n background: linear-gradient(135deg, #f0f8ff 0%, #e3f2fd 100%) !important;\n border: 2px solid var(--c-primary, #1976d2) !important;\n font-weight: bold;\n text-align: center;\n color: var(--c-primary, #1976d2);\n}\n.excel-container .excel-viewer .excel-table-container .excel-table .excel-cell.merged-cell[data-v-5569b81f]::before {\n content: \"\";\n position: absolute;\n top: 3px;\n left: 3px;\n right: 3px;\n bottom: 3px;\n background: rgba(25, 118, 210, 0.08);\n border-radius: 2px;\n pointer-events: none;\n}\n.excel-container .excel-viewer .excel-table-container .excel-table .excel-cell.merged-cell[data-v-5569b81f]::after {\n content: \"📎\";\n position: absolute;\n top: 2px;\n right: 4px;\n font-size: 10px;\n opacity: 0.6;\n}\n.excel-container .excel-viewer .excel-table-container .excel-table .excel-cell.compact-cell[data-v-5569b81f] {\n padding: 4px 8px;\n font-size: 12px;\n}\n.excel-container .excel-viewer .excel-table-container .excel-table .excel-cell.compact-cell.merged-cell[data-v-5569b81f] {\n background: linear-gradient(135deg, #f0f8ff 0%, #e3f2fd 100%) !important;\n border: 1px solid var(--c-primary, #1976d2) !important;\n font-weight: bold;\n text-align: center;\n color: var(--c-primary, #1976d2);\n}\n.excel-container .excel-viewer .excel-table-container .excel-table .excel-cell.compact-cell.merged-cell[data-v-5569b81f]::before {\n top: 2px;\n left: 2px;\n right: 2px;\n bottom: 2px;\n background: rgba(25, 118, 210, 0.05);\n}\n.excel-container .excel-viewer .excel-table-container .excel-table .excel-cell.compact-cell.merged-cell[data-v-5569b81f]::after {\n display: none;\n}\n.excel-container .excel-viewer .excel-table-container .excel-empty[data-v-5569b81f] {\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n min-height: 200px;\n}\n.excel-container .excel-viewer .excel-table-container .excel-pagination[data-v-5569b81f] {\n padding: 20px 16px;\n border-top: 1px solid var(--c-border, #e0e0e0);\n background-color: var(--c-bg-card, #f9f9f9);\n display: flex;\n justify-content: center;\n flex-shrink: 0;\n z-index: 1000;\n position: relative;\n overflow: visible;\n}\n.excel-container .excel-viewer .excel-table-container .excel-pagination[data-v-5569b81f] .n-pagination {\n z-index: 1001;\n position: relative;\n}\n.excel-container .excel-viewer .excel-table-container .excel-pagination[data-v-5569b81f] .n-pagination-size-picker {\n z-index: 1002;\n position: relative;\n}\n.excel-container .excel-viewer .excel-table-container .excel-pagination[data-v-5569b81f] .n-pagination-size-picker .n-base-selection {\n z-index: 1003;\n}\n.excel-container .excel-viewer .excel-table-container .excel-pagination[data-v-5569b81f] .n-pagination-size-picker .n-base-selection-popover {\n z-index: 1004 !important;\n}\n.excel-container .excel-viewer .excel-table-container .excel-pagination[data-v-5569b81f] .n-popover {\n z-index: 1005 !important;\n}","/* unplugin-vue-components disabled */.c-file-preview-wrapper[data-v-7c7c652b] {\n width: 100%;\n}\n.c-file-preview-wrapper .file-info-card .file-info[data-v-7c7c652b] {\n display: flex;\n align-items: center;\n gap: 16px;\n padding: 16px;\n border: 1px solid var(--c-border, #e0e0e0);\n border-radius: 12px;\n background: var(--c-bg-card, white);\n transition: var(--c-transition, 0.2s ease);\n cursor: pointer;\n}\n.c-file-preview-wrapper .file-info-card .file-info[data-v-7c7c652b]:hover {\n border-color: var(--c-primary, #40a9ff);\n box-shadow: 0 4px 12px rgba(64, 169, 255, 0.15);\n transform: translateY(-1px);\n}\n.c-file-preview-wrapper .file-info-card .file-info .file-icon[data-v-7c7c652b] {\n flex-shrink: 0;\n width: 56px;\n height: 56px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);\n border-radius: 12px;\n border: 1px solid #dee2e6;\n}\n.c-file-preview-wrapper .file-info-card .file-info .file-details[data-v-7c7c652b] {\n flex: 1;\n min-width: 0;\n}\n.c-file-preview-wrapper .file-info-card .file-info .file-details .file-name[data-v-7c7c652b] {\n display: flex;\n align-items: center;\n gap: 12px;\n margin-bottom: 6px;\n font-weight: 600;\n font-size: 16px;\n color: var(--c-text-1, #1f2937);\n}\n.c-file-preview-wrapper .file-info-card .file-info .file-details .file-meta[data-v-7c7c652b] {\n display: flex;\n gap: 16px;\n font-size: 13px;\n color: var(--c-text-2, #6b7280);\n}\n.c-file-preview-wrapper .file-info-card .file-info .file-details .file-meta .file-size[data-v-7c7c652b] {\n font-weight: 500;\n color: var(--c-text-1, #374151);\n}\n.c-file-preview-wrapper .file-info-card .file-info .file-actions[data-v-7c7c652b] {\n flex-shrink: 0;\n display: flex;\n gap: 8px;\n}\n.modal-container[data-v-7c7c652b] {\n background: var(--c-bg-card, white);\n border-radius: 8px;\n box-shadow: 0 20px 40px rgba(0, 0, 0, 0.15);\n display: flex;\n flex-direction: column;\n width: 100%;\n height: 100%;\n overflow: visible;\n}\n.modal-container .modal-header[data-v-7c7c652b] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 16px 20px;\n background: var(--c-bg, #fafafa);\n border-bottom: 1px solid var(--c-border, #e0e0e0);\n flex-shrink: 0;\n z-index: 10;\n position: relative;\n}\n.modal-container .modal-header .modal-title[data-v-7c7c652b] {\n display: flex;\n align-items: center;\n gap: 8px;\n font-weight: 600;\n font-size: 16px;\n color: var(--c-text-1, #333);\n}\n.modal-container .modal-header .modal-title span[data-v-7c7c652b] {\n max-width: 400px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.modal-container .modal-header .modal-actions[data-v-7c7c652b] {\n display: flex;\n gap: 8px;\n align-items: center;\n}\n.modal-container .modal-content[data-v-7c7c652b] {\n flex: 1;\n display: flex;\n flex-direction: column;\n overflow: visible;\n min-height: 0;\n}\n.modal-container .preview-header[data-v-7c7c652b] {\n padding: 16px;\n border-bottom: 1px solid var(--c-border, #e0e0e0);\n background-color: var(--c-bg-card, #f9f9f9);\n flex-shrink: 0;\n z-index: 9;\n position: relative;\n}\n.modal-container .preview-content[data-v-7c7c652b] {\n flex: 1;\n overflow: auto;\n min-height: 0;\n position: relative;\n}\n.modal-container .preview-content .status-container[data-v-7c7c652b] {\n height: 300px;\n display: flex;\n align-items: center;\n justify-content: center;\n}"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AChBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;ACvHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AClPA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"C_FilePreview.js","names":["XLSX","totalPages","pdfUrl","headings","content","sheets","$emit"],"sources":["../src/components/C_FilePreview/data.ts","../src/components/C_FilePreview/components/PdfViewer/index.vue","../src/components/C_FilePreview/components/PdfViewer/index.vue","../src/components/C_FilePreview/components/WordViewer/index.vue","../src/components/C_FilePreview/components/WordViewer/index.vue","../src/components/C_FilePreview/components/ExcelViewer/index.vue","../src/components/C_FilePreview/components/ExcelViewer/index.vue","../src/components/C_FilePreview/composables/useFilePreview.ts","../src/components/C_FilePreview/composables/useFullscreen.ts","../src/components/C_FilePreview/index.vue","../src/components/C_FilePreview/index.vue"],"sourcesContent":["/**\r\n * C_FilePreview 常量配置与工具函数\r\n * 类型定义统一在 ./types.ts\r\n */\r\nimport { type Ref } from \"vue\";\r\nimport * as XLSX from \"xlsx\";\r\nimport mammoth from \"mammoth\";\r\nimport type {\r\n FilePreviewType,\r\n FileConfig,\r\n ZoomConfig,\r\n ExcelRow,\r\n ExcelColumn,\r\n ExcelSheet,\r\n DocHeading,\r\n PdfLoadResult,\r\n WordLoadResult,\r\n ExcelLoadResult,\r\n} from \"./types\";\r\n\r\n/* ==================== 常量配置 ==================== */\r\n\r\nexport const FILE_TYPE_MAP: Record<string, FilePreviewType> = {\r\n pdf: \"pdf\",\r\n doc: \"word\",\r\n docx: \"word\",\r\n xls: \"excel\",\r\n xlsx: \"excel\",\r\n};\r\n\r\nexport const FILE_CONFIGS: Record<string, FileConfig> = {\r\n pdf: {\r\n tagType: \"error\",\r\n icon: \"ic:outline-picture-as-pdf\",\r\n color: \"#dc2626\",\r\n },\r\n word: { tagType: \"info\", icon: \"ic:outline-description\", color: \"#2563eb\" },\r\n excel: { tagType: \"success\", icon: \"ic:outline-grid-on\", color: \"#16a34a\" },\r\n unknown: {\r\n tagType: \"default\",\r\n icon: \"ic:outline-insert-drive-file\",\r\n color: \"#6b7280\",\r\n },\r\n};\r\n\r\nexport const ZOOM_CONFIGS: Record<string, ZoomConfig> = {\r\n pdf: { min: 0.5, max: 3, step: 0.25, default: 1 },\r\n word: { min: 50, max: 200, step: 10, default: 100 },\r\n};\r\n\r\nexport const PAGE_SIZE_OPTIONS = [20, 50, 100, 200];\r\n\r\nexport const FULLSCREEN_EVENTS = [\r\n \"fullscreenchange\",\r\n \"webkitfullscreenchange\",\r\n \"mozfullscreenchange\",\r\n \"MSFullscreenChange\",\r\n];\r\n\r\n/* ==================== 文件信息工具函数 ==================== */\r\n\r\nexport const extractFileNameFromUrl = (url: string): string => {\r\n try {\r\n const urlPath = url.split(\"/\").pop() || url.split(\"\\\\\").pop();\r\n if (urlPath?.includes(\".\")) {\r\n const decodedName = decodeURIComponent(urlPath.split(\"?\")[0]);\r\n if (decodedName && decodedName !== url) return decodedName;\r\n }\r\n } catch (error) {\r\n console.warn(\"解析URL文件名失败:\", error);\r\n }\r\n return \"未知文件\";\r\n};\r\n\r\nexport const formatFileSize = (bytes: number): string => {\r\n if (bytes === 0) return \"0 B\";\r\n const k = 1024;\r\n const sizes = [\"B\", \"KB\", \"MB\", \"GB\"];\r\n const i = Math.floor(Math.log(bytes) / Math.log(k));\r\n return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + \" \" + sizes[i];\r\n};\r\n\r\nexport const getFileType = (fileName: string): FilePreviewType => {\r\n if (!fileName || fileName === \"未知文件\") return \"unknown\";\r\n const ext = fileName.toLowerCase().split(\".\").pop();\r\n if (!ext) return \"unknown\";\r\n return FILE_TYPE_MAP[ext] || \"unknown\";\r\n};\r\n\r\nexport const getFileConfig = (fileType: string): FileConfig => {\r\n return FILE_CONFIGS[fileType] || FILE_CONFIGS.unknown;\r\n};\r\n\r\n/* ==================== 缩放工具 ==================== */\r\n\r\nexport const createZoomHandler = (\r\n valueRef: Ref<number>,\r\n config: ZoomConfig,\r\n) => {\r\n return (action: \"in\" | \"out\" | \"reset\") => {\r\n const { min, max, step, default: defaultValue } = config;\r\n switch (action) {\r\n case \"reset\":\r\n valueRef.value = defaultValue;\r\n break;\r\n case \"in\":\r\n if (valueRef.value < max) valueRef.value += step;\r\n break;\r\n case \"out\":\r\n if (valueRef.value > min) valueRef.value -= step;\r\n break;\r\n }\r\n };\r\n};\r\n\r\n/* ==================== Excel 工具函数 ==================== */\r\n\r\nexport const getColumnLetter = (index: number): string => {\r\n let result = \"\";\r\n while (index >= 0) {\r\n result = String.fromCharCode(65 + (index % 26)) + result;\r\n index = Math.floor(index / 26) - 1;\r\n }\r\n return result;\r\n};\r\n\r\nexport const formatCellValue = (value: any): string => {\r\n if (!value) return \"\";\r\n const strValue = String(value).trim();\r\n\r\n if (!isNaN(Number(strValue)) && strValue !== \"\" && strValue.length < 15) {\r\n const num = Number(strValue);\r\n return Number.isInteger(num)\r\n ? num.toLocaleString()\r\n : num.toLocaleString(undefined, { maximumFractionDigits: 2 });\r\n }\r\n return strValue;\r\n};\r\n\r\nexport const getCellClass = (value: any): string => {\r\n if (!value) return \"cell-empty\";\r\n const strValue = String(value).trim();\r\n\r\n if (!isNaN(Number(strValue)) && strValue !== \"\") return \"cell-number\";\r\n if (strValue.match(/[■▬▪▫─━]/)) return \"cell-gantt\";\r\n if (\r\n strValue.match(/^\\d{4}[-/]\\d{2}[-/]\\d{2}/) ||\r\n strValue.match(/^\\d{2}[-/]\\d{2}[-/]\\d{4}/)\r\n )\r\n return \"cell-date\";\r\n if ([\"true\", \"false\"].includes(strValue.toLowerCase())) return \"cell-boolean\";\r\n return strValue.length > 20 ? \"cell-text cell-long\" : \"cell-text\";\r\n};\r\n\r\nexport const processExcelSheet = (\r\n worksheet: any,\r\n merges: any[],\r\n): { data: ExcelRow[]; columns: ExcelColumn[] } => {\r\n const range = XLSX.utils.decode_range(worksheet[\"!ref\"] || \"A1:A1\");\r\n const { c: maxCol, r: maxRow } = range.e;\r\n\r\n const columns: ExcelColumn[] = Array.from({ length: maxCol + 1 }, (_, c) => {\r\n const cellAddress = XLSX.utils.encode_cell({ r: 0, c });\r\n const cell = worksheet[cellAddress];\r\n const columnName = cell ? String(cell.v || \"\").trim() : `列${c + 1}`;\r\n return {\r\n title: columnName || `列${c + 1}`,\r\n key: `col_${c}`,\r\n width: Math.min(Math.max(columnName.length * 12, 80), 200),\r\n };\r\n });\r\n\r\n const mergeMap = new Map();\r\n merges.forEach(({ s: { r: sRow, c: sCol }, e: { r: eRow, c: eCol } }) => {\r\n for (let r = sRow; r <= eRow; r++) {\r\n for (let c = sCol; c <= eCol; c++) {\r\n mergeMap.set(`${r}-${c}`, {\r\n isMain: r === sRow && c === sCol,\r\n rowspan: eRow - sRow + 1,\r\n colspan: eCol - sCol + 1,\r\n });\r\n }\r\n }\r\n });\r\n\r\n const data: ExcelRow[] = Array.from({ length: maxRow + 1 }, (_, r) => {\r\n const row: ExcelRow = {};\r\n for (let c = 0; c <= maxCol; c++) {\r\n const cellAddress = XLSX.utils.encode_cell({ r, c });\r\n const cell = worksheet[cellAddress];\r\n const mergeInfo = mergeMap.get(`${r}-${c}`);\r\n\r\n row[`col_${c}`] = {\r\n value: cell ? cell.v || \"\" : \"\",\r\n merged: !!mergeInfo,\r\n hidden: mergeInfo && !mergeInfo.isMain,\r\n rowspan: mergeInfo?.isMain ? mergeInfo.rowspan : 1,\r\n colspan: mergeInfo?.isMain ? mergeInfo.colspan : 1,\r\n };\r\n }\r\n return row;\r\n });\r\n\r\n return { data, columns };\r\n};\r\n\r\n/* ==================== 文件加载器 ==================== */\r\n\r\nexport async function loadPdf(file: File): Promise<PdfLoadResult> {\r\n const fileUrl = URL.createObjectURL(file);\r\n return {\r\n url: fileUrl + \"#toolbar=1&navpanes=1&scrollbar=1&view=FitH\",\r\n totalPages: 1,\r\n };\r\n}\r\n\r\nexport async function loadWord(file: File): Promise<WordLoadResult> {\r\n const arrayBuffer = await file.arrayBuffer();\r\n const result = await mammoth.convertToHtml({\r\n arrayBuffer,\r\n styleMap: [\r\n \"p[style-name='Heading 1'] => h1:fresh\",\r\n \"p[style-name='Heading 2'] => h2:fresh\",\r\n \"p[style-name='Heading 3'] => h3:fresh\",\r\n \"p[style-name='Title'] => h1.title:fresh\",\r\n ],\r\n } as any);\r\n\r\n let content = result.value;\r\n const headings: DocHeading[] = [];\r\n\r\n /* 提取标题并注入 id */\r\n const tempDiv = document.createElement(\"div\");\r\n tempDiv.innerHTML = content;\r\n const headingElements = tempDiv.querySelectorAll(\"h1, h2, h3, h4, h5, h6\");\r\n\r\n Array.from(headingElements).forEach((el, index) => {\r\n const id = `heading-${index}`;\r\n const level = parseInt(el.tagName.charAt(1));\r\n const text = el.textContent || \"\";\r\n\r\n content = content.replace(\r\n el.outerHTML,\r\n el.outerHTML.replace(\r\n el.tagName.toLowerCase(),\r\n `${el.tagName.toLowerCase()} id=\"${id}\"`,\r\n ),\r\n );\r\n\r\n headings.push({ id, text, level });\r\n });\r\n\r\n return { content, headings };\r\n}\r\n\r\nexport async function loadExcel(file: File): Promise<ExcelLoadResult> {\r\n const arrayBuffer = await file.arrayBuffer();\r\n const workbook = XLSX.read(arrayBuffer, {\r\n type: \"array\",\r\n cellStyles: true,\r\n cellFormula: true,\r\n cellDates: true,\r\n });\r\n\r\n if (!workbook.SheetNames.length) {\r\n throw new Error(\"Excel文件中没有找到工作表\");\r\n }\r\n\r\n const sheets: ExcelSheet[] = workbook.SheetNames.map((name) => {\r\n const worksheet = workbook.Sheets[name];\r\n const merges = worksheet[\"!merges\"] || [];\r\n const { data, columns } = processExcelSheet(worksheet, merges);\r\n return { name, data, merges, columns };\r\n });\r\n\r\n return { sheets };\r\n}\r\n","<!--\n PdfViewer — PDF 文件预览子组件\n 负责: 工具栏(翻页+缩放) + iframe 渲染\n-->\n<template>\n <div class=\"file-container pdf-container\">\n <div class=\"file-toolbar\">\n <div class=\"flex justify-between items-center\">\n <!-- 翻页控制 -->\n <div class=\"flex gap-2 items-center\">\n <NButton\n size=\"small\"\n :disabled=\"currentPage <= 1\"\n @click=\"changePage('prev')\"\n >\n <template #icon>\n <C_Icon name=\"ic:outline-chevron-left\" />\n </template>\n </NButton>\n <NInputNumber\n v-model:value=\"currentPage\"\n size=\"small\"\n :min=\"1\"\n :max=\"totalPages\"\n style=\"width: 80px\"\n @update:value=\"changePage as any\"\n />\n <span class=\"text-sm text-gray-600\">/ {{ totalPages }}</span>\n <NButton\n size=\"small\"\n :disabled=\"currentPage >= totalPages\"\n @click=\"changePage('next')\"\n >\n <template #icon>\n <C_Icon name=\"ic:outline-chevron-right\" />\n </template>\n </NButton>\n </div>\n\n <!-- 缩放控制 -->\n <div class=\"flex gap-2 items-center\">\n <NButton\n size=\"small\"\n :disabled=\"scale <= 0.5\"\n @click=\"adjustZoom('out')\"\n >\n <template #icon>\n <C_Icon name=\"ic:outline-zoom-out\" />\n </template>\n </NButton>\n <span class=\"text-sm text-gray-600 min-w-12 text-center\">\n {{ Math.round(scale * 100) }}%\n </span>\n <NButton\n size=\"small\"\n :disabled=\"scale >= 3\"\n @click=\"adjustZoom('in')\"\n >\n <template #icon>\n <C_Icon name=\"ic:outline-zoom-in\" />\n </template>\n </NButton>\n <NButton\n size=\"small\"\n @click=\"adjustZoom('reset')\"\n >\n <template #icon>\n <C_Icon name=\"ic:outline-fit-screen\" />\n </template>\n 适应\n </NButton>\n </div>\n </div>\n </div>\n\n <div class=\"file-viewer\">\n <iframe\n v-if=\"pdfUrl\"\n :src=\"pdfUrl\"\n class=\"w-full h-full border-0\"\n title=\"PDF预览\"\n frameborder=\"0\"\n allowfullscreen\n />\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\n import { ref } from 'vue'\n import { NButton, NInputNumber } from 'naive-ui'\n import { createZoomHandler, ZOOM_CONFIGS } from '../../data'\n\n const props = defineProps<{\n pdfUrl: string\n totalPages: number\n }>()\n\n const currentPage = ref(1)\n const scale = ref(1)\n\n const adjustZoom = createZoomHandler(scale, ZOOM_CONFIGS.pdf)\n\n const changePage = (action: 'prev' | 'next' | number) => {\n if (typeof action === 'number') {\n currentPage.value = Math.max(1, Math.min(action, props.totalPages))\n } else {\n const delta = action === 'prev' ? -1 : 1\n currentPage.value = Math.max(\n 1,\n Math.min(currentPage.value + delta, props.totalPages)\n )\n }\n }\n</script>\n\n<style lang=\"scss\" scoped>\n @use './index.scss';\n</style>\n","<!--\n PdfViewer — PDF 文件预览子组件\n 负责: 工具栏(翻页+缩放) + iframe 渲染\n-->\n<template>\n <div class=\"file-container pdf-container\">\n <div class=\"file-toolbar\">\n <div class=\"flex justify-between items-center\">\n <!-- 翻页控制 -->\n <div class=\"flex gap-2 items-center\">\n <NButton\n size=\"small\"\n :disabled=\"currentPage <= 1\"\n @click=\"changePage('prev')\"\n >\n <template #icon>\n <C_Icon name=\"ic:outline-chevron-left\" />\n </template>\n </NButton>\n <NInputNumber\n v-model:value=\"currentPage\"\n size=\"small\"\n :min=\"1\"\n :max=\"totalPages\"\n style=\"width: 80px\"\n @update:value=\"changePage as any\"\n />\n <span class=\"text-sm text-gray-600\">/ {{ totalPages }}</span>\n <NButton\n size=\"small\"\n :disabled=\"currentPage >= totalPages\"\n @click=\"changePage('next')\"\n >\n <template #icon>\n <C_Icon name=\"ic:outline-chevron-right\" />\n </template>\n </NButton>\n </div>\n\n <!-- 缩放控制 -->\n <div class=\"flex gap-2 items-center\">\n <NButton\n size=\"small\"\n :disabled=\"scale <= 0.5\"\n @click=\"adjustZoom('out')\"\n >\n <template #icon>\n <C_Icon name=\"ic:outline-zoom-out\" />\n </template>\n </NButton>\n <span class=\"text-sm text-gray-600 min-w-12 text-center\">\n {{ Math.round(scale * 100) }}%\n </span>\n <NButton\n size=\"small\"\n :disabled=\"scale >= 3\"\n @click=\"adjustZoom('in')\"\n >\n <template #icon>\n <C_Icon name=\"ic:outline-zoom-in\" />\n </template>\n </NButton>\n <NButton\n size=\"small\"\n @click=\"adjustZoom('reset')\"\n >\n <template #icon>\n <C_Icon name=\"ic:outline-fit-screen\" />\n </template>\n 适应\n </NButton>\n </div>\n </div>\n </div>\n\n <div class=\"file-viewer\">\n <iframe\n v-if=\"pdfUrl\"\n :src=\"pdfUrl\"\n class=\"w-full h-full border-0\"\n title=\"PDF预览\"\n frameborder=\"0\"\n allowfullscreen\n />\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\n import { ref } from 'vue'\n import { NButton, NInputNumber } from 'naive-ui'\n import { createZoomHandler, ZOOM_CONFIGS } from '../../data'\n\n const props = defineProps<{\n pdfUrl: string\n totalPages: number\n }>()\n\n const currentPage = ref(1)\n const scale = ref(1)\n\n const adjustZoom = createZoomHandler(scale, ZOOM_CONFIGS.pdf)\n\n const changePage = (action: 'prev' | 'next' | number) => {\n if (typeof action === 'number') {\n currentPage.value = Math.max(1, Math.min(action, props.totalPages))\n } else {\n const delta = action === 'prev' ? -1 : 1\n currentPage.value = Math.max(\n 1,\n Math.min(currentPage.value + delta, props.totalPages)\n )\n }\n }\n</script>\n\n<style lang=\"scss\" scoped>\n @use './index.scss';\n</style>\n","<!--\n WordViewer — Word 文档预览子组件\n 负责: 目录导航 + 缩放 + 文档内容渲染\n-->\n<template>\n <div class=\"file-container word-container\">\n <div class=\"file-toolbar\">\n <div class=\"flex gap-2 items-center\">\n <NButton size=\"small\" @click=\"showOutline = !showOutline\">\n <template #icon>\n <C_Icon name=\"ic:outline-list\" />\n </template>\n {{ showOutline ? \"隐藏\" : \"显示\" }}目录\n </NButton>\n <NDivider vertical />\n <NButton\n size=\"small\"\n :disabled=\"wordZoom <= 50\"\n @click=\"adjustWordZoom('out')\"\n >\n <template #icon>\n <C_Icon name=\"ic:outline-zoom-out\" />\n </template>\n </NButton>\n <span class=\"text-sm text-gray-600 min-w-12 text-center\">\n {{ wordZoom }}%\n </span>\n <NButton\n size=\"small\"\n :disabled=\"wordZoom >= 200\"\n @click=\"adjustWordZoom('in')\"\n >\n <template #icon>\n <C_Icon name=\"ic:outline-zoom-in\" />\n </template>\n </NButton>\n <NButton size=\"small\" @click=\"adjustWordZoom('reset')\">\n <template #icon>\n <C_Icon name=\"ic:outline-fit-screen\" />\n </template>\n 重置\n </NButton>\n </div>\n </div>\n\n <div class=\"word-layout\">\n <div class=\"word-main\">\n <!-- 侧边栏目录 -->\n <div v-if=\"showOutline\" class=\"word-outline\">\n <div class=\"outline-header\">\n <h3 class=\"text-sm font-semibold\">文档目录</h3>\n </div>\n <div class=\"outline-content\">\n <div\n v-for=\"(heading, index) in headings\"\n :key=\"index\"\n class=\"outline-item\"\n :class=\"`level-${heading.level}`\"\n @click=\"scrollToHeading(heading.id)\"\n >\n {{ heading.text }}\n </div>\n </div>\n </div>\n\n <!-- 主要内容区域 -->\n <div class=\"word-content\">\n <div\n class=\"word-document\"\n :style=\"{\n transform: `scale(${wordZoom / 100})`,\n transformOrigin: 'top center',\n }\"\n v-html=\"content\"\n ></div>\n </div>\n </div>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref } from \"vue\";\nimport { NButton, NDivider } from \"naive-ui\";\nimport { createZoomHandler, ZOOM_CONFIGS } from \"../../data\";\nimport type { DocHeading } from \"../../types\";\n\ndefineProps<{\n content: string;\n headings: DocHeading[];\n}>();\n\nconst showOutline = ref(true);\nconst wordZoom = ref(100);\n\nconst adjustWordZoom = createZoomHandler(wordZoom, ZOOM_CONFIGS.word);\n\nconst scrollToHeading = (headingId: string) => {\n document\n .getElementById(headingId)\n ?.scrollIntoView({ behavior: \"smooth\", block: \"start\" });\n};\n</script>\n\n<style lang=\"scss\" scoped>\n@use \"./index.scss\";\n</style>\n","<!--\n WordViewer — Word 文档预览子组件\n 负责: 目录导航 + 缩放 + 文档内容渲染\n-->\n<template>\n <div class=\"file-container word-container\">\n <div class=\"file-toolbar\">\n <div class=\"flex gap-2 items-center\">\n <NButton size=\"small\" @click=\"showOutline = !showOutline\">\n <template #icon>\n <C_Icon name=\"ic:outline-list\" />\n </template>\n {{ showOutline ? \"隐藏\" : \"显示\" }}目录\n </NButton>\n <NDivider vertical />\n <NButton\n size=\"small\"\n :disabled=\"wordZoom <= 50\"\n @click=\"adjustWordZoom('out')\"\n >\n <template #icon>\n <C_Icon name=\"ic:outline-zoom-out\" />\n </template>\n </NButton>\n <span class=\"text-sm text-gray-600 min-w-12 text-center\">\n {{ wordZoom }}%\n </span>\n <NButton\n size=\"small\"\n :disabled=\"wordZoom >= 200\"\n @click=\"adjustWordZoom('in')\"\n >\n <template #icon>\n <C_Icon name=\"ic:outline-zoom-in\" />\n </template>\n </NButton>\n <NButton size=\"small\" @click=\"adjustWordZoom('reset')\">\n <template #icon>\n <C_Icon name=\"ic:outline-fit-screen\" />\n </template>\n 重置\n </NButton>\n </div>\n </div>\n\n <div class=\"word-layout\">\n <div class=\"word-main\">\n <!-- 侧边栏目录 -->\n <div v-if=\"showOutline\" class=\"word-outline\">\n <div class=\"outline-header\">\n <h3 class=\"text-sm font-semibold\">文档目录</h3>\n </div>\n <div class=\"outline-content\">\n <div\n v-for=\"(heading, index) in headings\"\n :key=\"index\"\n class=\"outline-item\"\n :class=\"`level-${heading.level}`\"\n @click=\"scrollToHeading(heading.id)\"\n >\n {{ heading.text }}\n </div>\n </div>\n </div>\n\n <!-- 主要内容区域 -->\n <div class=\"word-content\">\n <div\n class=\"word-document\"\n :style=\"{\n transform: `scale(${wordZoom / 100})`,\n transformOrigin: 'top center',\n }\"\n v-html=\"content\"\n ></div>\n </div>\n </div>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref } from \"vue\";\nimport { NButton, NDivider } from \"naive-ui\";\nimport { createZoomHandler, ZOOM_CONFIGS } from \"../../data\";\nimport type { DocHeading } from \"../../types\";\n\ndefineProps<{\n content: string;\n headings: DocHeading[];\n}>();\n\nconst showOutline = ref(true);\nconst wordZoom = ref(100);\n\nconst adjustWordZoom = createZoomHandler(wordZoom, ZOOM_CONFIGS.word);\n\nconst scrollToHeading = (headingId: string) => {\n document\n .getElementById(headingId)\n ?.scrollIntoView({ behavior: \"smooth\", block: \"start\" });\n};\n</script>\n\n<style lang=\"scss\" scoped>\n@use \"./index.scss\";\n</style>\n","<!--\n ExcelViewer — Excel 表格预览子组件\n 负责: 工作表切换 + 表格渲染(合并单元格) + 分页 + 格式切换\n-->\n<template>\n <div class=\"file-container excel-container\">\n <!-- 工具栏 -->\n <div class=\"file-toolbar\">\n <div class=\"flex justify-between items-center\">\n <div class=\"flex gap-2 items-center\">\n <NTabs\n v-if=\"sheets.length > 1\"\n v-model:value=\"activeSheet\"\n type=\"card\"\n size=\"small\"\n >\n <NTabPane\n v-for=\"sheet in sheets\"\n :key=\"sheet.name\"\n :name=\"sheet.name\"\n :tab=\"sheet.name\"\n />\n </NTabs>\n <span v-else class=\"text-sm text-gray-600\">\n 工作表: {{ activeSheet }}\n </span>\n </div>\n\n <div class=\"flex gap-2 items-center\">\n <NButton size=\"small\" @click=\"showExcelFormat = !showExcelFormat\">\n <template #icon>\n <C_Icon name=\"ic:outline-format-paint\" />\n </template>\n {{ showExcelFormat ? \"紧凑视图\" : \"完整格式\" }}\n </NButton>\n </div>\n </div>\n </div>\n\n <div class=\"excel-viewer\">\n <!-- 信息面板 -->\n <div v-if=\"currentData.length > 0\" class=\"excel-info\">\n <NText depth=\"3\" class=\"text-sm\">\n 当前工作表: {{ activeSheet }} | 总行数: {{ currentData.length }} |\n 总列数: {{ currentColumns.length }} | 当前页:\n {{ currentExcelPage }}/{{ totalExcelPages }}\n </NText>\n </div>\n\n <!-- 表格 -->\n <div class=\"excel-table-container\">\n <div\n class=\"excel-table-wrapper\"\n :class=\"{ 'simple-mode': !showExcelFormat }\"\n >\n <table v-if=\"currentData.length > 0\" class=\"excel-table\">\n <thead>\n <tr>\n <th class=\"row-number\">行号</th>\n <th\n v-for=\"(col, index) in currentColumns\"\n :key=\"col.key\"\n class=\"excel-header\"\n :style=\"{ minWidth: col.width + 'px' }\"\n >\n <div class=\"header-content\">\n <span class=\"column-letter\">{{\n getColumnLetter(index)\n }}</span>\n <span class=\"column-title\">{{ col.title }}</span>\n </div>\n </th>\n </tr>\n </thead>\n <tbody>\n <tr\n v-for=\"(row, rowIndex) in paginatedData\"\n :key=\"rowIndex\"\n class=\"excel-row\"\n >\n <td class=\"row-number\">\n {{ (currentExcelPage - 1) * pageSize + rowIndex + 1 }}\n </td>\n <td\n v-for=\"col in currentColumns\"\n :key=\"col.key\"\n v-show=\"!row[col.key]?.hidden\"\n class=\"excel-cell\"\n :class=\"[\n getCellClass(row[col.key]?.value),\n row[col.key]?.merged ? 'merged-cell' : '',\n !showExcelFormat ? 'compact-cell' : '',\n ]\"\n :rowspan=\"row[col.key]?.rowspan || 1\"\n :colspan=\"row[col.key]?.colspan || 1\"\n :title=\"row[col.key]?.value\"\n >\n {{ formatCellValue(row[col.key]?.value) }}\n </td>\n </tr>\n </tbody>\n </table>\n\n <div v-else class=\"excel-empty\">\n <NEmpty description=\"该工作表没有数据或解析失败\">\n <template #extra>\n <NButton size=\"small\" @click=\"$emit('reload')\">\n 重新解析\n </NButton>\n </template>\n </NEmpty>\n </div>\n </div>\n\n <!-- 分页 -->\n <div v-if=\"totalExcelPages > 1\" class=\"excel-pagination\">\n <NPagination\n v-model:page=\"currentExcelPage\"\n :page-count=\"totalExcelPages\"\n :page-size=\"pageSize\"\n show-size-picker\n :page-sizes=\"PAGE_SIZE_OPTIONS\"\n @update:page-size=\"handlePageSizeChange\"\n />\n </div>\n </div>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, computed, watch } from \"vue\";\nimport { NButton, NTabs, NTabPane, NText, NEmpty, NPagination } from \"naive-ui\";\nimport {\n getColumnLetter,\n formatCellValue,\n getCellClass,\n PAGE_SIZE_OPTIONS,\n} from \"../../data\";\nimport type { ExcelSheet, ExcelRow, ExcelColumn } from \"../../types\";\n\nconst props = defineProps<{\n sheets: ExcelSheet[];\n}>();\n\ndefineEmits<{\n reload: [];\n}>();\n\n/* ==================== 内部状态 ==================== */\nconst activeSheet = ref(\"\");\nconst showExcelFormat = ref(false);\nconst currentExcelPage = ref(1);\nconst pageSize = ref(50);\n\n/* ==================== 当前工作表数据 ==================== */\nconst currentData = ref<ExcelRow[]>([]);\nconst currentColumns = ref<ExcelColumn[]>([]);\n\n/* ==================== 计算属性 ==================== */\nconst totalExcelPages = computed(() =>\n Math.ceil(currentData.value.length / pageSize.value),\n);\n\nconst paginatedData = computed(() => {\n const start = (currentExcelPage.value - 1) * pageSize.value;\n return currentData.value.slice(start, start + pageSize.value);\n});\n\n/* ==================== 方法 ==================== */\nconst handlePageSizeChange = (newPageSize: number) => {\n pageSize.value = newPageSize;\n currentExcelPage.value = 1;\n};\n\nconst syncSheetData = (sheetName: string) => {\n const sheet = props.sheets.find((s) => s.name === sheetName);\n if (sheet) {\n currentData.value = sheet.data;\n currentColumns.value = sheet.columns;\n currentExcelPage.value = 1;\n }\n};\n\n/* ==================== 监听器 ==================== */\nwatch(activeSheet, (newSheet) => {\n syncSheetData(newSheet);\n});\n\n/* sheets 变化时初始化 */\nwatch(\n () => props.sheets,\n (newSheets) => {\n if (newSheets.length > 0) {\n const [firstSheet] = newSheets;\n activeSheet.value = firstSheet.name;\n currentData.value = firstSheet.data;\n currentColumns.value = firstSheet.columns;\n currentExcelPage.value = 1;\n }\n },\n { immediate: true },\n);\n</script>\n\n<style lang=\"scss\" scoped>\n@use \"./index.scss\";\n</style>\n","<!--\n ExcelViewer — Excel 表格预览子组件\n 负责: 工作表切换 + 表格渲染(合并单元格) + 分页 + 格式切换\n-->\n<template>\n <div class=\"file-container excel-container\">\n <!-- 工具栏 -->\n <div class=\"file-toolbar\">\n <div class=\"flex justify-between items-center\">\n <div class=\"flex gap-2 items-center\">\n <NTabs\n v-if=\"sheets.length > 1\"\n v-model:value=\"activeSheet\"\n type=\"card\"\n size=\"small\"\n >\n <NTabPane\n v-for=\"sheet in sheets\"\n :key=\"sheet.name\"\n :name=\"sheet.name\"\n :tab=\"sheet.name\"\n />\n </NTabs>\n <span v-else class=\"text-sm text-gray-600\">\n 工作表: {{ activeSheet }}\n </span>\n </div>\n\n <div class=\"flex gap-2 items-center\">\n <NButton size=\"small\" @click=\"showExcelFormat = !showExcelFormat\">\n <template #icon>\n <C_Icon name=\"ic:outline-format-paint\" />\n </template>\n {{ showExcelFormat ? \"紧凑视图\" : \"完整格式\" }}\n </NButton>\n </div>\n </div>\n </div>\n\n <div class=\"excel-viewer\">\n <!-- 信息面板 -->\n <div v-if=\"currentData.length > 0\" class=\"excel-info\">\n <NText depth=\"3\" class=\"text-sm\">\n 当前工作表: {{ activeSheet }} | 总行数: {{ currentData.length }} |\n 总列数: {{ currentColumns.length }} | 当前页:\n {{ currentExcelPage }}/{{ totalExcelPages }}\n </NText>\n </div>\n\n <!-- 表格 -->\n <div class=\"excel-table-container\">\n <div\n class=\"excel-table-wrapper\"\n :class=\"{ 'simple-mode': !showExcelFormat }\"\n >\n <table v-if=\"currentData.length > 0\" class=\"excel-table\">\n <thead>\n <tr>\n <th class=\"row-number\">行号</th>\n <th\n v-for=\"(col, index) in currentColumns\"\n :key=\"col.key\"\n class=\"excel-header\"\n :style=\"{ minWidth: col.width + 'px' }\"\n >\n <div class=\"header-content\">\n <span class=\"column-letter\">{{\n getColumnLetter(index)\n }}</span>\n <span class=\"column-title\">{{ col.title }}</span>\n </div>\n </th>\n </tr>\n </thead>\n <tbody>\n <tr\n v-for=\"(row, rowIndex) in paginatedData\"\n :key=\"rowIndex\"\n class=\"excel-row\"\n >\n <td class=\"row-number\">\n {{ (currentExcelPage - 1) * pageSize + rowIndex + 1 }}\n </td>\n <td\n v-for=\"col in currentColumns\"\n :key=\"col.key\"\n v-show=\"!row[col.key]?.hidden\"\n class=\"excel-cell\"\n :class=\"[\n getCellClass(row[col.key]?.value),\n row[col.key]?.merged ? 'merged-cell' : '',\n !showExcelFormat ? 'compact-cell' : '',\n ]\"\n :rowspan=\"row[col.key]?.rowspan || 1\"\n :colspan=\"row[col.key]?.colspan || 1\"\n :title=\"row[col.key]?.value\"\n >\n {{ formatCellValue(row[col.key]?.value) }}\n </td>\n </tr>\n </tbody>\n </table>\n\n <div v-else class=\"excel-empty\">\n <NEmpty description=\"该工作表没有数据或解析失败\">\n <template #extra>\n <NButton size=\"small\" @click=\"$emit('reload')\">\n 重新解析\n </NButton>\n </template>\n </NEmpty>\n </div>\n </div>\n\n <!-- 分页 -->\n <div v-if=\"totalExcelPages > 1\" class=\"excel-pagination\">\n <NPagination\n v-model:page=\"currentExcelPage\"\n :page-count=\"totalExcelPages\"\n :page-size=\"pageSize\"\n show-size-picker\n :page-sizes=\"PAGE_SIZE_OPTIONS\"\n @update:page-size=\"handlePageSizeChange\"\n />\n </div>\n </div>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, computed, watch } from \"vue\";\nimport { NButton, NTabs, NTabPane, NText, NEmpty, NPagination } from \"naive-ui\";\nimport {\n getColumnLetter,\n formatCellValue,\n getCellClass,\n PAGE_SIZE_OPTIONS,\n} from \"../../data\";\nimport type { ExcelSheet, ExcelRow, ExcelColumn } from \"../../types\";\n\nconst props = defineProps<{\n sheets: ExcelSheet[];\n}>();\n\ndefineEmits<{\n reload: [];\n}>();\n\n/* ==================== 内部状态 ==================== */\nconst activeSheet = ref(\"\");\nconst showExcelFormat = ref(false);\nconst currentExcelPage = ref(1);\nconst pageSize = ref(50);\n\n/* ==================== 当前工作表数据 ==================== */\nconst currentData = ref<ExcelRow[]>([]);\nconst currentColumns = ref<ExcelColumn[]>([]);\n\n/* ==================== 计算属性 ==================== */\nconst totalExcelPages = computed(() =>\n Math.ceil(currentData.value.length / pageSize.value),\n);\n\nconst paginatedData = computed(() => {\n const start = (currentExcelPage.value - 1) * pageSize.value;\n return currentData.value.slice(start, start + pageSize.value);\n});\n\n/* ==================== 方法 ==================== */\nconst handlePageSizeChange = (newPageSize: number) => {\n pageSize.value = newPageSize;\n currentExcelPage.value = 1;\n};\n\nconst syncSheetData = (sheetName: string) => {\n const sheet = props.sheets.find((s) => s.name === sheetName);\n if (sheet) {\n currentData.value = sheet.data;\n currentColumns.value = sheet.columns;\n currentExcelPage.value = 1;\n }\n};\n\n/* ==================== 监听器 ==================== */\nwatch(activeSheet, (newSheet) => {\n syncSheetData(newSheet);\n});\n\n/* sheets 变化时初始化 */\nwatch(\n () => props.sheets,\n (newSheets) => {\n if (newSheets.length > 0) {\n const [firstSheet] = newSheets;\n activeSheet.value = firstSheet.name;\n currentData.value = firstSheet.data;\n currentColumns.value = firstSheet.columns;\n currentExcelPage.value = 1;\n }\n },\n { immediate: true },\n);\n</script>\n\n<style lang=\"scss\" scoped>\n@use \"./index.scss\";\n</style>\n","/**\r\n * useFilePreview — 文件预览核心 composable\r\n * 管理:文件状态、加载、类型检测、下载\r\n */\r\nimport { ref, computed, watch, onUnmounted, type Ref } from \"vue\";\r\nimport {\r\n extractFileNameFromUrl,\r\n getFileType,\r\n getFileConfig,\r\n loadPdf,\r\n loadWord,\r\n loadExcel,\r\n} from \"../data\";\r\nimport type { FilePreviewType, DocHeading, ExcelSheet } from \"../types\";\r\n\r\nexport interface UseFilePreviewOptions {\r\n file: Ref<File | undefined>;\r\n url: Ref<string | undefined>;\r\n fileName: Ref<string>;\r\n}\r\n\r\n/**\r\n * 文件预览核心 composable — 管理文件状态、加载、类型检测、下载\r\n * @param options - 文件源配置(file / url / fileName)\r\n * @param emit - 组件事件发射器\r\n */\r\nexport function useFilePreview(\r\n options: UseFilePreviewOptions,\r\n emit: {\r\n (e: \"preview\", file: File | string): void;\r\n (e: \"download\", file: File | string): void;\r\n },\r\n) {\r\n const { file, url, fileName } = options;\r\n\r\n /* ==================== 基础状态 ==================== */\r\n const loading = ref(false);\r\n const error = ref(\"\");\r\n const fileSize = ref(0);\r\n const showModal = ref(false);\r\n\r\n /* ==================== 解析后的数据 ==================== */\r\n const pdfUrl = ref(\"\");\r\n const pdfTotalPages = ref(0);\r\n\r\n const wordContent = ref(\"\");\r\n const wordHeadings = ref<DocHeading[]>([]);\r\n\r\n const excelSheets = ref<ExcelSheet[]>([]);\r\n\r\n /* ==================== 计算属性 ==================== */\r\n const displayFileName = computed(() => {\r\n if (fileName.value && fileName.value !== \"未知文件\") return fileName.value;\r\n if (file.value?.name) return file.value.name;\r\n if (url.value) return extractFileNameFromUrl(url.value);\r\n return \"未知文件\";\r\n });\r\n\r\n const fileType = computed<FilePreviewType>(() =>\r\n getFileType(displayFileName.value),\r\n );\r\n const fileConfig = computed(() => getFileConfig(fileType.value));\r\n\r\n /* ==================== 内部方法 ==================== */\r\n const clearState = () => {\r\n error.value = \"\";\r\n loading.value = false;\r\n pdfUrl.value = \"\";\r\n pdfTotalPages.value = 0;\r\n wordContent.value = \"\";\r\n wordHeadings.value = [];\r\n excelSheets.value = [];\r\n };\r\n\r\n const setError = (msg: string) => {\r\n error.value = msg;\r\n loading.value = false;\r\n };\r\n\r\n /* ==================== 文件解析 ==================== */\r\n const resolveFile = async (): Promise<File> => {\r\n if (file.value) {\r\n fileSize.value = file.value.size;\r\n return file.value;\r\n }\r\n if (url.value) {\r\n const response = await fetch(url.value);\r\n if (!response.ok)\r\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\r\n\r\n const blob = await response.blob();\r\n const resolved = new File([blob], displayFileName.value, {\r\n type: blob.type,\r\n });\r\n fileSize.value = resolved.size;\r\n return resolved;\r\n }\r\n throw new Error(\"未提供文件或URL\");\r\n };\r\n\r\n const loadByType = async (\r\n currentFile: File,\r\n type: FilePreviewType,\r\n ): Promise<void> => {\r\n switch (type) {\r\n case \"pdf\": {\r\n const result = await loadPdf(currentFile);\r\n pdfUrl.value = result.url;\r\n pdfTotalPages.value = result.totalPages;\r\n break;\r\n }\r\n case \"word\": {\r\n const result = await loadWord(currentFile);\r\n wordContent.value = result.content;\r\n wordHeadings.value = result.headings;\r\n break;\r\n }\r\n case \"excel\": {\r\n const result = await loadExcel(currentFile);\r\n excelSheets.value = result.sheets;\r\n break;\r\n }\r\n default:\r\n throw new Error(\"不支持的文件格式\");\r\n }\r\n };\r\n\r\n /* ==================== 核心方法 ==================== */\r\n const loadFile = async () => {\r\n if (!file.value && !url.value) {\r\n setError(\"未提供文件或URL\");\r\n return;\r\n }\r\n\r\n clearState();\r\n loading.value = true;\r\n\r\n try {\r\n const currentFile = await resolveFile();\r\n await loadByType(currentFile, fileType.value);\r\n loading.value = false;\r\n } catch (err) {\r\n const errorMessage = err instanceof Error ? err.message : \"未知错误\";\r\n setError(`${fileType.value.toUpperCase()}文件加载失败: ${errorMessage}`);\r\n }\r\n };\r\n\r\n const openPreview = async () => {\r\n showModal.value = true;\r\n await loadFile();\r\n emit(\"preview\", file.value || url.value!);\r\n };\r\n\r\n const downloadFile = () => {\r\n if (file.value) {\r\n const downloadUrl = URL.createObjectURL(file.value);\r\n const a = Object.assign(document.createElement(\"a\"), {\r\n href: downloadUrl,\r\n download: displayFileName.value,\r\n });\r\n a.click();\r\n URL.revokeObjectURL(downloadUrl);\r\n } else if (url.value) {\r\n window.open(url.value, \"_blank\");\r\n }\r\n emit(\"download\", file.value || url.value!);\r\n };\r\n\r\n /* ==================== 副作用 ==================== */\r\n watch(\r\n () => file.value?.size,\r\n (newSize) => {\r\n fileSize.value = newSize || 0;\r\n },\r\n { immediate: true },\r\n );\r\n\r\n onUnmounted(() => {\r\n if (pdfUrl.value?.startsWith(\"blob:\")) {\r\n URL.revokeObjectURL(pdfUrl.value.split(\"#\")[0]);\r\n }\r\n });\r\n\r\n return {\r\n /* 状态 */\r\n loading,\r\n error,\r\n fileSize,\r\n showModal,\r\n /* 解析数据 */\r\n pdfUrl,\r\n pdfTotalPages,\r\n wordContent,\r\n wordHeadings,\r\n excelSheets,\r\n /* 计算属性 */\r\n displayFileName,\r\n fileType,\r\n fileConfig,\r\n /* 方法 */\r\n loadFile,\r\n openPreview,\r\n downloadFile,\r\n };\r\n}\r\n","/**\r\n * useFullscreen — 全屏切换 composable\r\n */\r\nimport { ref, onMounted, onUnmounted, type Ref } from \"vue\";\r\nimport { FULLSCREEN_EVENTS } from \"../data\";\r\n\r\n/**\r\n * 全屏切换 composable — 管理全屏状态与跨浏览器兼容\r\n * @param containerRef - 需要全屏的容器元素引用\r\n */\r\nexport function useFullscreen(containerRef: Ref<HTMLElement | undefined>) {\r\n const isFullscreen = ref(false);\r\n\r\n const handleFullscreenChange = () => {\r\n isFullscreen.value = !!document.fullscreenElement;\r\n };\r\n\r\n const tryMethods = (\r\n methods: Array<() => Promise<void>>,\r\n index = 0,\r\n ): Promise<void> => {\r\n if (index >= methods.length) {\r\n console.warn(\"无法切换全屏状态\");\r\n return Promise.resolve();\r\n }\r\n return methods[index]().catch(() => tryMethods(methods, index + 1));\r\n };\r\n\r\n const toggleFullscreen = async () => {\r\n const element = containerRef.value;\r\n if (!element) return;\r\n\r\n const isCurrentlyFullscreen = !!document.fullscreenElement;\r\n\r\n const methods = isCurrentlyFullscreen\r\n ? [\r\n () => document.exitFullscreen(),\r\n () => (document as any).webkitExitFullscreen(),\r\n () => (document as any).mozCancelFullScreen(),\r\n () => (document as any).msExitFullscreen(),\r\n ]\r\n : [\r\n () => element.requestFullscreen(),\r\n () => (element as any).webkitRequestFullscreen(),\r\n () => (element as any).mozRequestFullScreen(),\r\n () => (element as any).msRequestFullscreen(),\r\n ];\r\n\r\n await tryMethods(methods);\r\n };\r\n\r\n const exitFullscreen = async () => {\r\n if (document.fullscreenElement) {\r\n try {\r\n await document.exitFullscreen();\r\n } catch {\r\n /* ignore */\r\n }\r\n }\r\n isFullscreen.value = false;\r\n };\r\n\r\n onMounted(() => {\r\n FULLSCREEN_EVENTS.forEach((event) =>\r\n document.addEventListener(event, handleFullscreenChange),\r\n );\r\n });\r\n\r\n onUnmounted(() => {\r\n FULLSCREEN_EVENTS.forEach((event) =>\r\n document.removeEventListener(event, handleFullscreenChange),\r\n );\r\n });\r\n\r\n return { isFullscreen, toggleFullscreen, exitFullscreen };\r\n}\r\n","<!--\n * @Author: ChenYu ycyplus@gmail.com\n * @Date: 2025-07-01\n * @Description: 文件预览组件(PDF/Word/Excel)\n * @Migration: naive-ui-components 组件库迁移版本\n * Copyright (c) 2025 by CHENY, All Rights Reserved.\n-->\n\n<template>\n <div class=\"c-file-preview-wrapper\">\n <!-- 文件信息卡片模式 -->\n <div\n v-if=\"!autoPreview\"\n class=\"file-info-card\"\n >\n <div class=\"file-info\">\n <div class=\"file-icon\">\n <C_Icon\n :name=\"fileConfig.icon\"\n :size=\"40\"\n :color=\"fileConfig.color\"\n />\n </div>\n\n <div class=\"file-details\">\n <div class=\"file-name\">\n <NEllipsis style=\"max-width: 250px\">{{\n displayFileName\n }}</NEllipsis>\n <NTag\n :type=\"fileConfig.tagType as any\"\n size=\"small\"\n >\n {{ fileType.toUpperCase() }}\n </NTag>\n </div>\n\n <div class=\"file-meta\">\n <span class=\"file-size\">{{ formatFileSize(fileSize) }}</span>\n </div>\n </div>\n\n <div class=\"file-actions\">\n <NButton\n type=\"primary\"\n @click=\"openPreview\"\n >\n <template #icon>\n <C_Icon name=\"ic:outline-visibility\" />\n </template>\n 预览\n </NButton>\n\n <NButton\n type=\"tertiary\"\n @click=\"downloadFile\"\n >\n <template #icon>\n <C_Icon name=\"ic:outline-download\" />\n </template>\n 下载\n </NButton>\n </div>\n </div>\n </div>\n\n <!-- 模态框预览 -->\n <NModal\n v-model:show=\"showModal\"\n :mask-closable=\"false\"\n :closable=\"false\"\n :auto-focus=\"false\"\n transform-origin=\"center\"\n style=\"\n width: 85vw;\n max-width: 1200px;\n min-width: 800px;\n height: 75vh;\n max-height: 700px;\n min-height: 500px;\n \"\n >\n <div\n ref=\"modalContainer\"\n class=\"modal-container\"\n >\n <!-- 自定义头部 -->\n <div class=\"modal-header\">\n <div class=\"modal-title\">\n <C_Icon\n :name=\"fileConfig.icon\"\n :size=\"20\"\n :color=\"fileConfig.color\"\n />\n <span>{{ displayFileName }}</span>\n </div>\n <div class=\"modal-actions\">\n <NButton\n size=\"small\"\n type=\"tertiary\"\n @click=\"downloadFile\"\n >\n <template #icon>\n <C_Icon name=\"ic:outline-download\" />\n </template>\n 下载\n </NButton>\n <NButton\n size=\"small\"\n type=\"tertiary\"\n @click=\"showModal = false\"\n >\n <template #icon>\n <C_Icon name=\"ic:outline-close\" />\n </template>\n </NButton>\n </div>\n </div>\n\n <!-- 预览内容 -->\n <div class=\"modal-content\">\n <!-- 文件信息头部 -->\n <div class=\"preview-header\">\n <div class=\"flex justify-between items-center\">\n <div class=\"flex items-center gap-3\">\n <NTag\n :type=\"fileConfig.tagType as any\"\n size=\"small\"\n >\n <template #icon>\n <C_Icon :name=\"fileConfig.icon\" />\n </template>\n {{ fileType.toUpperCase() }}\n </NTag>\n <NEllipsis style=\"max-width: 300px\">{{\n displayFileName\n }}</NEllipsis>\n <span class=\"text-sm text-gray-500\">{{\n formatFileSize(fileSize)\n }}</span>\n </div>\n\n <div class=\"flex gap-2\">\n <NButton\n size=\"small\"\n type=\"tertiary\"\n :disabled=\"loading\"\n @click=\"loadFile\"\n >\n <template #icon>\n <C_Icon name=\"ic:outline-refresh\" />\n </template>\n 刷新\n </NButton>\n <NButton\n size=\"small\"\n type=\"primary\"\n @click=\"toggleFullscreen\"\n >\n <template #icon>\n <C_Icon\n :name=\"\n isFullscreen\n ? 'ic:outline-fullscreen-exit'\n : 'ic:outline-fullscreen'\n \"\n />\n </template>\n {{ isFullscreen ? '退出全屏' : '全屏' }}\n </NButton>\n </div>\n </div>\n </div>\n\n <!-- 预览内容区域 -->\n <div class=\"preview-content\">\n <!-- 加载和错误状态 -->\n <template v-if=\"loading || error\">\n <div class=\"status-container\">\n <NSpin\n v-if=\"loading\"\n size=\"large\"\n >\n <template #description>\n 正在加载{{ fileType.toUpperCase() }}文件...\n </template>\n </NSpin>\n <NResult\n v-else\n status=\"error\"\n title=\"预览失败\"\n :description=\"error\"\n >\n <template #footer>\n <NButton @click=\"loadFile\">重试</NButton>\n </template>\n </NResult>\n </div>\n </template>\n\n <!-- 文件预览 — 委托给子组件 -->\n <template v-else>\n <PdfViewer\n v-if=\"fileType === 'pdf'\"\n :pdf-url=\"pdfUrl\"\n :total-pages=\"pdfTotalPages\"\n />\n\n <WordViewer\n v-else-if=\"fileType === 'word'\"\n :content=\"wordContent\"\n :headings=\"wordHeadings\"\n />\n\n <ExcelViewer\n v-else-if=\"fileType === 'excel'\"\n :sheets=\"excelSheets\"\n @reload=\"loadFile\"\n />\n\n <!-- 不支持的文件类型 -->\n <NResult\n v-else\n status=\"warning\"\n title=\"不支持的文件格式\"\n :description=\"`暂不支持预览 ${fileType.toUpperCase()} 格式文件`\"\n />\n </template>\n </div>\n </div>\n </div>\n </NModal>\n </div>\n</template>\n\n<script setup lang=\"ts\">\n import { ref, toRefs, watch } from 'vue'\n import { NButton, NEllipsis, NTag, NModal, NSpin, NResult } from 'naive-ui'\n import { formatFileSize } from './data'\n import PdfViewer from './components/PdfViewer/index.vue'\n import WordViewer from './components/WordViewer/index.vue'\n import ExcelViewer from './components/ExcelViewer/index.vue'\n import { useFilePreview } from './composables/useFilePreview'\n import { useFullscreen } from './composables/useFullscreen'\n\n defineOptions({ name: 'C_FilePreview' })\n\n const props = withDefaults(\n defineProps<{\n file?: File\n url?: string\n fileName?: string\n autoPreview?: boolean\n }>(),\n {\n fileName: '未知文件',\n autoPreview: false,\n }\n )\n\n const { file, url, fileName: propFileName, autoPreview } = toRefs(props)\n\n const emit = defineEmits<{\n preview: [file: File | string]\n download: [file: File | string]\n }>()\n\n /* ==================== Composables ==================== */\n const {\n loading,\n error,\n fileSize,\n showModal,\n pdfUrl,\n pdfTotalPages,\n wordContent,\n wordHeadings,\n excelSheets,\n displayFileName,\n fileType,\n fileConfig,\n loadFile,\n openPreview,\n downloadFile,\n } = useFilePreview({ file, url, fileName: propFileName }, emit)\n\n const modalContainer = ref<HTMLElement>()\n const { isFullscreen, toggleFullscreen, exitFullscreen } =\n useFullscreen(modalContainer)\n\n /* ==================== Modal 关闭时退出全屏 ==================== */\n watch(showModal, isShow => {\n if (!isShow) exitFullscreen()\n })\n</script>\n\n<style lang=\"scss\" scoped>\n @use './index.scss';\n</style>\n","<!--\n * @Author: ChenYu ycyplus@gmail.com\n * @Date: 2025-07-01\n * @Description: 文件预览组件(PDF/Word/Excel)\n * @Migration: naive-ui-components 组件库迁移版本\n * Copyright (c) 2025 by CHENY, All Rights Reserved.\n-->\n\n<template>\n <div class=\"c-file-preview-wrapper\">\n <!-- 文件信息卡片模式 -->\n <div\n v-if=\"!autoPreview\"\n class=\"file-info-card\"\n >\n <div class=\"file-info\">\n <div class=\"file-icon\">\n <C_Icon\n :name=\"fileConfig.icon\"\n :size=\"40\"\n :color=\"fileConfig.color\"\n />\n </div>\n\n <div class=\"file-details\">\n <div class=\"file-name\">\n <NEllipsis style=\"max-width: 250px\">{{\n displayFileName\n }}</NEllipsis>\n <NTag\n :type=\"fileConfig.tagType as any\"\n size=\"small\"\n >\n {{ fileType.toUpperCase() }}\n </NTag>\n </div>\n\n <div class=\"file-meta\">\n <span class=\"file-size\">{{ formatFileSize(fileSize) }}</span>\n </div>\n </div>\n\n <div class=\"file-actions\">\n <NButton\n type=\"primary\"\n @click=\"openPreview\"\n >\n <template #icon>\n <C_Icon name=\"ic:outline-visibility\" />\n </template>\n 预览\n </NButton>\n\n <NButton\n type=\"tertiary\"\n @click=\"downloadFile\"\n >\n <template #icon>\n <C_Icon name=\"ic:outline-download\" />\n </template>\n 下载\n </NButton>\n </div>\n </div>\n </div>\n\n <!-- 模态框预览 -->\n <NModal\n v-model:show=\"showModal\"\n :mask-closable=\"false\"\n :closable=\"false\"\n :auto-focus=\"false\"\n transform-origin=\"center\"\n style=\"\n width: 85vw;\n max-width: 1200px;\n min-width: 800px;\n height: 75vh;\n max-height: 700px;\n min-height: 500px;\n \"\n >\n <div\n ref=\"modalContainer\"\n class=\"modal-container\"\n >\n <!-- 自定义头部 -->\n <div class=\"modal-header\">\n <div class=\"modal-title\">\n <C_Icon\n :name=\"fileConfig.icon\"\n :size=\"20\"\n :color=\"fileConfig.color\"\n />\n <span>{{ displayFileName }}</span>\n </div>\n <div class=\"modal-actions\">\n <NButton\n size=\"small\"\n type=\"tertiary\"\n @click=\"downloadFile\"\n >\n <template #icon>\n <C_Icon name=\"ic:outline-download\" />\n </template>\n 下载\n </NButton>\n <NButton\n size=\"small\"\n type=\"tertiary\"\n @click=\"showModal = false\"\n >\n <template #icon>\n <C_Icon name=\"ic:outline-close\" />\n </template>\n </NButton>\n </div>\n </div>\n\n <!-- 预览内容 -->\n <div class=\"modal-content\">\n <!-- 文件信息头部 -->\n <div class=\"preview-header\">\n <div class=\"flex justify-between items-center\">\n <div class=\"flex items-center gap-3\">\n <NTag\n :type=\"fileConfig.tagType as any\"\n size=\"small\"\n >\n <template #icon>\n <C_Icon :name=\"fileConfig.icon\" />\n </template>\n {{ fileType.toUpperCase() }}\n </NTag>\n <NEllipsis style=\"max-width: 300px\">{{\n displayFileName\n }}</NEllipsis>\n <span class=\"text-sm text-gray-500\">{{\n formatFileSize(fileSize)\n }}</span>\n </div>\n\n <div class=\"flex gap-2\">\n <NButton\n size=\"small\"\n type=\"tertiary\"\n :disabled=\"loading\"\n @click=\"loadFile\"\n >\n <template #icon>\n <C_Icon name=\"ic:outline-refresh\" />\n </template>\n 刷新\n </NButton>\n <NButton\n size=\"small\"\n type=\"primary\"\n @click=\"toggleFullscreen\"\n >\n <template #icon>\n <C_Icon\n :name=\"\n isFullscreen\n ? 'ic:outline-fullscreen-exit'\n : 'ic:outline-fullscreen'\n \"\n />\n </template>\n {{ isFullscreen ? '退出全屏' : '全屏' }}\n </NButton>\n </div>\n </div>\n </div>\n\n <!-- 预览内容区域 -->\n <div class=\"preview-content\">\n <!-- 加载和错误状态 -->\n <template v-if=\"loading || error\">\n <div class=\"status-container\">\n <NSpin\n v-if=\"loading\"\n size=\"large\"\n >\n <template #description>\n 正在加载{{ fileType.toUpperCase() }}文件...\n </template>\n </NSpin>\n <NResult\n v-else\n status=\"error\"\n title=\"预览失败\"\n :description=\"error\"\n >\n <template #footer>\n <NButton @click=\"loadFile\">重试</NButton>\n </template>\n </NResult>\n </div>\n </template>\n\n <!-- 文件预览 — 委托给子组件 -->\n <template v-else>\n <PdfViewer\n v-if=\"fileType === 'pdf'\"\n :pdf-url=\"pdfUrl\"\n :total-pages=\"pdfTotalPages\"\n />\n\n <WordViewer\n v-else-if=\"fileType === 'word'\"\n :content=\"wordContent\"\n :headings=\"wordHeadings\"\n />\n\n <ExcelViewer\n v-else-if=\"fileType === 'excel'\"\n :sheets=\"excelSheets\"\n @reload=\"loadFile\"\n />\n\n <!-- 不支持的文件类型 -->\n <NResult\n v-else\n status=\"warning\"\n title=\"不支持的文件格式\"\n :description=\"`暂不支持预览 ${fileType.toUpperCase()} 格式文件`\"\n />\n </template>\n </div>\n </div>\n </div>\n </NModal>\n </div>\n</template>\n\n<script setup lang=\"ts\">\n import { ref, toRefs, watch } from 'vue'\n import { NButton, NEllipsis, NTag, NModal, NSpin, NResult } from 'naive-ui'\n import { formatFileSize } from './data'\n import PdfViewer from './components/PdfViewer/index.vue'\n import WordViewer from './components/WordViewer/index.vue'\n import ExcelViewer from './components/ExcelViewer/index.vue'\n import { useFilePreview } from './composables/useFilePreview'\n import { useFullscreen } from './composables/useFullscreen'\n\n defineOptions({ name: 'C_FilePreview' })\n\n const props = withDefaults(\n defineProps<{\n file?: File\n url?: string\n fileName?: string\n autoPreview?: boolean\n }>(),\n {\n fileName: '未知文件',\n autoPreview: false,\n }\n )\n\n const { file, url, fileName: propFileName, autoPreview } = toRefs(props)\n\n const emit = defineEmits<{\n preview: [file: File | string]\n download: [file: File | string]\n }>()\n\n /* ==================== Composables ==================== */\n const {\n loading,\n error,\n fileSize,\n showModal,\n pdfUrl,\n pdfTotalPages,\n wordContent,\n wordHeadings,\n excelSheets,\n displayFileName,\n fileType,\n fileConfig,\n loadFile,\n openPreview,\n downloadFile,\n } = useFilePreview({ file, url, fileName: propFileName }, emit)\n\n const modalContainer = ref<HTMLElement>()\n const { isFullscreen, toggleFullscreen, exitFullscreen } =\n useFullscreen(modalContainer)\n\n /* ==================== Modal 关闭时退出全屏 ==================== */\n watch(showModal, isShow => {\n if (!isShow) exitFullscreen()\n })\n</script>\n\n<style lang=\"scss\" scoped>\n @use './index.scss';\n</style>\n"],"mappings":"+LAsBA,MAAa,EAAiD,CAC5D,IAAK,MACL,IAAK,OACL,KAAM,OACN,IAAK,QACL,KAAM,QACP,CAEY,EAA2C,CACtD,IAAK,CACH,QAAS,QACT,KAAM,4BACN,MAAO,UACR,CACD,KAAM,CAAE,QAAS,OAAQ,KAAM,yBAA0B,MAAO,UAAW,CAC3E,MAAO,CAAE,QAAS,UAAW,KAAM,qBAAsB,MAAO,UAAW,CAC3E,QAAS,CACP,QAAS,UACT,KAAM,+BACN,MAAO,UACR,CACF,CAEY,EAA2C,CACtD,IAAK,CAAE,IAAK,GAAK,IAAK,EAAG,KAAM,IAAM,QAAS,EAAG,CACjD,KAAM,CAAE,IAAK,GAAI,IAAK,IAAK,KAAM,GAAI,QAAS,IAAK,CACpD,CAEY,EAAoB,CAAC,GAAI,GAAI,IAAK,IAAI,CAEtC,EAAoB,CAC/B,mBACA,yBACA,sBACA,qBACD,CAIY,EAA0B,GAAwB,CAC7D,GAAI,CACF,IAAM,EAAU,EAAI,MAAM,IAAI,CAAC,KAAK,EAAI,EAAI,MAAM,KAAK,CAAC,KAAK,CAC7D,GAAI,GAAS,SAAS,IAAI,CAAE,CAC1B,IAAM,EAAc,mBAAmB,EAAQ,MAAM,IAAI,CAAC,GAAG,CAC7D,GAAI,GAAe,IAAgB,EAAK,OAAO,SAE1C,EAAO,CACd,QAAQ,KAAK,cAAe,EAAM,CAEpC,MAAO,QAGI,EAAkB,GAA0B,CACvD,GAAI,IAAU,EAAG,MAAO,MACxB,IAAM,EAAI,KACJ,EAAQ,CAAC,IAAK,KAAM,KAAM,KAAK,CAC/B,EAAI,KAAK,MAAM,KAAK,IAAI,EAAM,CAAG,KAAK,IAAI,EAAE,CAAC,CACnD,OAAO,YAAY,EAAiB,IAAG,GAAI,QAAQ,EAAE,CAAC,CAAG,IAAM,EAAM,IAG1D,EAAe,GAAsC,CAChE,GAAI,CAAC,GAAY,IAAa,OAAQ,MAAO,UAC7C,IAAM,EAAM,EAAS,aAAa,CAAC,MAAM,IAAI,CAAC,KAAK,CAEnD,OADK,GACE,EAAc,IADJ,WAIN,EAAiB,GACrB,EAAa,IAAa,EAAa,QAKnC,GACX,EACA,IAEQ,GAAmC,CACzC,GAAM,CAAE,MAAK,MAAK,OAAM,QAAS,GAAiB,EAClD,OAAQ,EAAR,CACE,IAAK,QACH,EAAS,MAAQ,EACjB,MACF,IAAK,KACC,EAAS,MAAQ,IAAK,EAAS,OAAS,GAC5C,MACF,IAAK,MACC,EAAS,MAAQ,IAAK,EAAS,OAAS,GAC5C,QAOK,EAAmB,GAA0B,CACxD,IAAI,EAAS,GACb,KAAO,GAAS,GACd,EAAS,OAAO,aAAa,GAAM,EAAQ,GAAI,CAAG,EAClD,EAAQ,KAAK,MAAM,EAAQ,GAAG,CAAG,EAEnC,OAAO,GAGI,EAAmB,GAAuB,CACrD,GAAI,CAAC,EAAO,MAAO,GACnB,IAAM,EAAW,OAAO,EAAM,CAAC,MAAM,CAErC,GAAI,CAAC,MAAM,OAAO,EAAS,CAAC,EAAI,IAAa,IAAM,EAAS,OAAS,GAAI,CACvE,IAAM,EAAM,OAAO,EAAS,CAC5B,OAAO,OAAO,UAAU,EAAI,CACxB,EAAI,gBAAgB,CACpB,EAAI,eAAe,IAAA,GAAW,CAAE,sBAAuB,EAAG,CAAC,CAEjE,OAAO,GAGI,EAAgB,GAAuB,CAClD,GAAI,CAAC,EAAO,MAAO,aACnB,IAAM,EAAW,OAAO,EAAM,CAAC,MAAM,CAUrC,MARI,CAAC,MAAM,OAAO,EAAS,CAAC,EAAI,IAAa,GAAW,cACpD,EAAS,MAAM,WAAW,CAAS,aAErC,EAAS,MAAM,2BAA2B,EAC1C,EAAS,MAAM,2BAA2B,CAEnC,YACL,CAAC,OAAQ,QAAQ,CAAC,SAAS,EAAS,aAAa,CAAC,CAAS,eACxD,EAAS,OAAS,GAAK,sBAAwB,aAG3C,GACX,EACA,IACiD,CAEjD,GAAM,CAAE,EAAG,EAAW,GADRA,EAAK,MAAM,aAAa,EAAU,SAAW,QAAQ,CAC5B,EAEjC,EAAyB,MAAM,KAAK,CAAE,OAAQ,EAAS,EAAG,EAAG,EAAG,IAAM,CAE1E,IAAM,EAAO,EADOA,EAAK,MAAM,YAAY,CAAE,EAAG,EAAG,IAAG,CAAC,EAEjD,EAAa,EAAO,OAAO,EAAK,GAAK,GAAG,CAAC,MAAM,CAAG,IAAI,EAAI,IAChE,MAAO,CACL,MAAO,GAAc,IAAI,EAAI,IAC7B,IAAK,OAAO,IACZ,MAAO,KAAK,IAAI,KAAK,IAAI,EAAW,OAAS,GAAI,GAAG,CAAE,IAAI,CAC3D,EACD,CAEI,EAAW,IAAI,IA+BrB,OA9BA,EAAO,SAAS,CAAE,EAAG,CAAE,EAAG,EAAM,EAAG,GAAQ,EAAG,CAAE,EAAG,EAAM,EAAG,MAAa,CACvE,IAAK,IAAI,EAAI,EAAM,GAAK,EAAM,IAC5B,IAAK,IAAI,EAAI,EAAM,GAAK,EAAM,IAC5B,EAAS,IAAI,GAAG,EAAE,GAAG,IAAK,CACxB,OAAQ,IAAM,GAAQ,IAAM,EAC5B,QAAS,EAAO,EAAO,EACvB,QAAS,EAAO,EAAO,EACxB,CAAC,EAGN,CAoBK,CAAE,KAlBgB,MAAM,KAAK,CAAE,OAAQ,EAAS,EAAG,EAAG,EAAG,IAAM,CACpE,IAAM,EAAgB,EAAE,CACxB,IAAK,IAAI,EAAI,EAAG,GAAK,EAAQ,IAAK,CAEhC,IAAM,EAAO,EADOA,EAAK,MAAM,YAAY,CAAE,EAAG,IAAG,CAAC,EAE9C,EAAY,EAAS,IAAI,GAAG,EAAE,GAAG,IAAI,CAE3C,EAAI,OAAO,KAAO,CAChB,MAAO,GAAO,EAAK,GAAU,GAC7B,OAAQ,CAAC,CAAC,EACV,OAAQ,GAAa,CAAC,EAAU,OAChC,QAAS,GAAW,OAAS,EAAU,QAAU,EACjD,QAAS,GAAW,OAAS,EAAU,QAAU,EAClD,CAEH,OAAO,GACP,CAEa,UAAS,EAK1B,eAAsB,EAAQ,EAAoC,CAEhE,MAAO,CACL,IAFc,IAAI,gBAAgB,EAAK,CAExB,8CACf,WAAY,EACb,CAGH,eAAsB,EAAS,EAAqC,CAClE,IAAM,EAAc,MAAM,EAAK,aAAa,CAWxC,GAVW,MAAM,EAAA,QAAQ,cAAc,CACzC,cACA,SAAU,CACR,wCACA,wCACA,wCACA,0CACD,CACF,CAAQ,EAEY,MACf,EAAyB,EAAE,CAG3B,EAAU,SAAS,cAAc,MAAM,CAC7C,EAAQ,UAAY,EACpB,IAAM,EAAkB,EAAQ,iBAAiB,yBAAyB,CAkB1E,OAhBA,MAAM,KAAK,EAAgB,CAAC,SAAS,EAAI,IAAU,CACjD,IAAM,EAAK,WAAW,IAChB,EAAQ,SAAS,EAAG,QAAQ,OAAO,EAAE,CAAC,CACtC,EAAO,EAAG,aAAe,GAE/B,EAAU,EAAQ,QAChB,EAAG,UACH,EAAG,UAAU,QACX,EAAG,QAAQ,aAAa,CACxB,GAAG,EAAG,QAAQ,aAAa,CAAC,OAAO,EAAG,GACvC,CACF,CAED,EAAS,KAAK,CAAE,KAAI,OAAM,QAAO,CAAC,EAClC,CAEK,CAAE,UAAS,WAAU,CAG9B,eAAsB,EAAU,EAAsC,CACpE,IAAM,EAAc,MAAM,EAAK,aAAa,CACtC,EAAWA,EAAK,KAAK,EAAa,CACtC,KAAM,QACN,WAAY,GACZ,YAAa,GACb,UAAW,GACZ,CAAC,CAEF,GAAI,CAAC,EAAS,WAAW,OACvB,MAAU,MAAM,kBAAkB,CAUpC,MAAO,CAAE,OAPoB,EAAS,WAAW,IAAK,GAAS,CAC7D,IAAM,EAAY,EAAS,OAAO,GAC5B,EAAS,EAAU,YAAc,EAAE,CACnC,CAAE,OAAM,WAAY,EAAkB,EAAW,EAAO,CAC9D,MAAO,CAAE,OAAM,OAAM,SAAQ,UAAS,EACtC,CAEe,+YCtLjB,IAAM,EAAQ,EAKR,GAAA,EAAA,EAAA,KAAkB,EAAC,CACnB,GAAA,EAAA,EAAA,KAAY,EAAC,CAEb,EAAa,EAAkB,EAAO,EAAa,IAAG,CAEtD,EAAc,GAAqC,CACvD,GAAI,OAAO,GAAW,SACpB,EAAY,MAAQ,KAAK,IAAI,EAAG,KAAK,IAAI,EAAQ,EAAM,WAAW,CAAA,KAC7D,CACL,IAAM,EAAQ,IAAW,OAAS,GAAK,EACvC,EAAY,MAAQ,KAAK,IACvB,EACA,KAAK,IAAI,EAAY,MAAQ,EAAO,EAAM,WAAU,CACtD,4EC1BE,MAhFN,EAgFM,EAAA,EAAA,EAAA,oBAZE,MAnEN,EAmEM,EAAA,EAAA,EAAA,oBADE,MAjEN,EAiEM,0BAhEJ,SAAa,0BA6BP,MA5BN,EA4BM,+BAnBM,EAAA,QAAA,CAAA,CAPR,KAAK,QACJ,SAAU,EAAA,OAAW,EACrB,QAAK,AAAA,EAAA,KAAA,GAAE,EAAU,OAAA,GAEP,MAAA,EAAA,EAAA,aACgC,EAAA,EAAA,EAAA,aAAA,EAAA,CAAjC,KAAK,0BAAyB,CAAA,CAAA,CAAA,oDAUxC,EAAA,aAAA,CAAA,CANQ,MAAO,EAAA,kCAAA,EAAW,MAAA,EAKX,EAAA,CAJf,KAAK,QACJ,IAAK,EACL,IAAKC,EAAAA,WACN,MAAA,CAAA,MAAA,OAAA,oEAG2D,OAA7D,EAAoC,MAAA,EAAA,EAAA,iBAAKA,EAAAA,WAAU,CAAA,EAAA,+BASzC,EAAA,QAAA,CAAA,CAPR,KAAK,QACJ,SAAU,EAAA,OAAeA,EAAAA,WACzB,QAAK,AAAA,EAAA,KAAA,GAAE,EAAU,OAAA,GAEP,MAAA,EAAA,EAAA,aACiC,EAAA,EAAA,EAAA,aAAA,EAAA,CAAlC,KAAK,2BAA0B,CAAA,CAAA,CAAA,iDAK7C,SAAa,0BAgCP,MA/BN,GA+BM,+BAtBM,EAAA,QAAA,CAAA,CAPR,KAAK,QACJ,SAAU,EAAA,OAAK,GACf,QAAK,AAAA,EAAA,KAAA,IAAA,EAAA,EAAA,OAAE,EAAU,CAAA,MAAA,GAEP,MAAA,EAAA,EAAA,aAC4B,EAAA,EAAA,EAAA,aAAA,EAAA,CAA7B,KAAK,sBAAqB,CAAA,CAAA,CAAA,+CAK/B,OAFP,IAAA,EAAA,EAAA,iBACK,KAAK,MAAM,EAAA,MAAK,IAAA,CAAA,CAAU,KAC/B,EAAA,+BASU,EAAA,QAAA,CAAA,CAPR,KAAK,QACJ,SAAU,EAAA,OAAK,EACf,QAAK,AAAA,EAAA,KAAA,IAAA,EAAA,EAAA,OAAE,EAAU,CAAA,KAAA,GAEP,MAAA,EAAA,EAAA,aAC2B,EAAA,EAAA,EAAA,aAAA,EAAA,CAA5B,KAAK,qBAAoB,CAAA,CAAA,CAAA,oDAW3B,EAAA,QAAA,CAAA,CAPR,KAAK,QACJ,QAAK,AAAA,EAAA,KAAA,IAAA,EAAA,EAAA,OAAE,EAAU,CAAA,QAAA,GAEP,MAAA,EAAA,EAAA,aAC8B,EAAA,EAAA,EAAA,aAAA,EAAA,CAA/B,KAAK,wBAAuB,CAAA,CAAA,CAAA,2BAGxC,CAAA,AAAA,EAAA,MAAA,EAAA,EAAA,iBAFa,OAEb,GAAA,CAAA,CAAA,6CAcA,MATN,GASM,CAPIC,EAAAA,SAAAA,EAAAA,EAAAA,YAAAA,EAAAA,EAAAA,EAAAA,oBAMN,SAAA,OALC,IAAKA,EAAAA,OACN,MAAM,yBACN,MAAM,QACN,YAAY,IACZ,gBAAA,+fCUR,IAAM,GAAA,EAAA,EAAA,KAAkB,GAAK,CACvB,GAAA,EAAA,EAAA,KAAe,IAAI,CAEnB,EAAiB,EAAkB,EAAU,EAAa,KAAK,CAE/D,EAAmB,GAAsB,CAC7C,SACG,eAAe,EAAS,EACvB,eAAe,CAAE,SAAU,SAAU,MAAO,QAAS,CAAC,2ECtBpD,MAzEN,EAyEM,EAAA,EAAA,EAAA,oBAnCE,MArCN,EAqCM,EAAA,EAAA,EAAA,oBADE,MAnCN,EAmCM,+BA7BM,EAAA,QAAA,CAAA,CALD,KAAK,QAAS,QAAK,AAAA,EAAA,KAAA,GAAE,EAAA,MAAW,CAAI,EAAA,QAChC,MAAA,EAAA,EAAA,aACwB,EAAA,EAAA,EAAA,aAAA,EAAA,CAAzB,KAAK,kBAAiB,CAAA,CAAA,CAAA,2BAEhC,EAAA,EAAA,EAAA,iBADW,KAAA,EAAA,EAAA,iBACR,EAAA,MAAW,KAAA,KAAA,CAAiB,MACjC,EAAA,CAAA,CAAA,qCACqB,EAAA,SAAA,CAAA,CAAX,SAAA,GAAQ,CAAA,+BASR,EAAA,QAAA,CAAA,CAPR,KAAK,QACJ,SAAU,EAAA,OAAQ,GAClB,QAAK,AAAA,EAAA,KAAA,IAAA,EAAA,EAAA,OAAE,EAAc,CAAA,MAAA,GAEX,MAAA,EAAA,EAAA,aAC4B,EAAA,EAAA,EAAA,aAAA,EAAA,CAA7B,KAAK,sBAAqB,CAAA,CAAA,CAAA,+CAK/B,OAFP,GAAA,EAAA,EAAA,iBACK,EAAA,MAAQ,CAAG,KAChB,EAAA,+BASU,EAAA,QAAA,CAAA,CAPR,KAAK,QACJ,SAAU,EAAA,OAAQ,IAClB,QAAK,AAAA,EAAA,KAAA,IAAA,EAAA,EAAA,OAAE,EAAc,CAAA,KAAA,GAEX,MAAA,EAAA,EAAA,aAC2B,EAAA,EAAA,EAAA,aAAA,EAAA,CAA5B,KAAK,qBAAoB,CAAA,CAAA,CAAA,oDAQ3B,EAAA,QAAA,CAAA,CALD,KAAK,QAAS,QAAK,AAAA,EAAA,KAAA,IAAA,EAAA,EAAA,OAAE,EAAc,CAAA,QAAA,GAC/B,MAAA,EAAA,EAAA,aAC8B,EAAA,EAAA,EAAA,aAAA,EAAA,CAA/B,KAAK,wBAAuB,CAAA,CAAA,CAAA,2BAGxC,CAAA,AAAA,EAAA,MAAA,EAAA,EAAA,iBAFa,OAEb,GAAA,CAAA,CAAA,2CAoCE,MAhCN,EAgCM,EAAA,EAAA,EAAA,oBADE,MA9BN,EA8BM,0BA7BJ,UAAc,CACH,EAAA,QAAA,EAAA,EAAA,YAAA,EAAA,EAAA,EAAA,oBAeL,MAfN,EAeM,CAAA,AAAA,EAAA,MAAA,EAAA,EAAA,oBAZE,MAAA,CAFD,MAAM,iBAAgB,CAAA,EAAA,EAAA,EAAA,oBACkB,KAAA,CAAvC,MAAM,wBAAuB,CAAC,OAAI,CAAA,CAAA,GAAA,EAAA,EAAA,EAAA,oBAYlC,MAVN,EAUM,GAAA,EAAA,EAAA,WAAA,GAAA,EAAA,EAAA,EAAA,oBADE,EAAA,SAAA,MAAA,EAAA,EAAA,YAPuBC,EAAAA,UAAnB,EAAS,gDAOb,MAAA,CANH,IAAK,EACN,OAAA,EAAA,EAAA,gBAAK,CAAC,eAAc,SACH,EAAQ,QAAK,CAAA,CAC7B,QAAK,GAAE,EAAgB,EAAQ,GAAA,wBAE7B,EAAQ,KAAI,CAAA,GAAA,EAAA,2EAKrB,WAAe,0BAUT,MATN,EASM,EAAA,EAAA,EAAA,oBADG,MAAA,CANL,MAAM,gBACL,OAAA,EAAA,EAAA,gBAAK,oBAAsC,EAAA,MAAQ,IAAA,kCAIpD,UAAQC,EAAAA,ktBCoEpB,IAAM,EAAQ,EASR,GAAA,EAAA,EAAA,KAAkB,GAAG,CACrB,GAAA,EAAA,EAAA,KAAsB,GAAM,CAC5B,GAAA,EAAA,EAAA,KAAuB,EAAE,CACzB,GAAA,EAAA,EAAA,KAAe,GAAG,CAGlB,GAAA,EAAA,EAAA,KAA8B,EAAE,CAAC,CACjC,GAAA,EAAA,EAAA,KAAoC,EAAE,CAAC,CAGvC,GAAA,EAAA,EAAA,cACJ,KAAK,KAAK,EAAY,MAAM,OAAS,EAAS,MAAM,CACrD,CAEK,GAAA,EAAA,EAAA,cAA+B,CACnC,IAAM,GAAS,EAAiB,MAAQ,GAAK,EAAS,MACtD,OAAO,EAAY,MAAM,MAAM,EAAO,EAAQ,EAAS,MAAM,EAC7D,CAGI,EAAwB,GAAwB,CACpD,EAAS,MAAQ,EACjB,EAAiB,MAAQ,GAGrB,EAAiB,GAAsB,CAC3C,IAAM,EAAQ,EAAM,OAAO,KAAM,GAAM,EAAE,OAAS,EAAU,CACxD,IACF,EAAY,MAAQ,EAAM,KAC1B,EAAe,MAAQ,EAAM,QAC7B,EAAiB,MAAQ,WAK7B,EAAA,EAAA,OAAM,EAAc,GAAa,CAC/B,EAAc,EAAS,EACvB,EAGF,EAAA,EAAA,WACQ,EAAM,OACX,GAAc,CACb,GAAI,EAAU,OAAS,EAAG,CACxB,GAAM,CAAC,GAAc,EACrB,EAAY,MAAQ,EAAW,KAC/B,EAAY,MAAQ,EAAW,KAC/B,EAAe,MAAQ,EAAW,QAClC,EAAiB,MAAQ,IAG7B,CAAE,UAAW,GAAM,CACpB,oEC3EO,MA1HN,EA0HM,0BAzHJ,QAAY,0BA+BN,MA9BN,EA8BM,EAAA,EAAA,EAAA,oBADE,MA5BN,EA4BM,EAAA,EAAA,EAAA,oBAVE,MAjBN,EAiBM,CAfIC,EAAAA,OAAO,OAAM,IAAA,EAAA,EAAA,YAAA,EAAA,EAAA,EAAA,cAAA,EAAA,EAAA,OAWb,EAAA,MAAA,CAAA,OAVE,MAAO,EAAA,iCAAA,EAAW,MAAA,EAC1B,KAAK,OACL,KAAK,oCAGoB,GAAA,EAAA,EAAA,WAAA,GAAA,EAAA,EAAA,EAAA,oBAIvB,EAAA,SAAA,MAAA,EAAA,EAAA,YAJgBA,EAAAA,OAAT,oDAIP,EAAA,SAAA,CAAA,CAHC,IAAK,EAAM,KACX,KAAM,EAAM,KACZ,IAAK,EAAM,sGAKT,OAFP,EAA2C,UAAA,EAAA,EAAA,iBACjC,EAAA,MAAW,CAAA,EAAA,EAAA,CAAA,EAAA,EAAA,EAAA,oBAWjB,MAPN,EAOM,EAAA,EAAA,EAAA,cAAA,EAAA,EAAA,OADM,EAAA,QAAA,CAAA,CALD,KAAK,QAAS,QAAK,AAAA,EAAA,KAAA,GAAE,EAAA,MAAe,CAAI,EAAA,QACpC,MAAA,EAAA,EAAA,aACgC,EAAA,EAAA,EAAA,aAAA,EAAA,CAAjC,KAAK,0BAAyB,CAAA,CAAA,CAAA,2BAExC,EAAA,EAAA,EAAA,iBADW,KAAA,EAAA,EAAA,iBACR,EAAA,MAAe,OAAA,OAAA,CAAA,EAAA,CAAA,CAAA,sCA6FpB,MAvFN,EAuFM,0BAtFJ,SAAa,CACF,EAAA,MAAY,OAAM,IAAA,EAAA,EAAA,YAAA,EAAA,EAAA,EAAA,oBAMvB,MANN,GAMM,EAAA,EAAA,EAAA,cAAA,EAAA,EAAA,OADI,EAAA,MAAA,CAAA,CAJD,MAAM,IAAI,MAAM,sCACd,EAAA,EAAA,EAAA,iBADwB,YAAA,EAAA,EAAA,iBACrB,EAAA,MAAW,CAAG,YAAA,EAAA,EAAA,iBAAW,EAAA,MAAY,OAAM,CAAG,YAAA,EAAA,EAAA,iBAChD,EAAA,MAAe,OAAM,CAAG,YAAA,EAAA,EAAA,iBAC7B,EAAA,MAAgB,CAAG,KAAA,EAAA,EAAA,iBAAI,EAAA,MAAe,CAAA,EAAA,CAAA,CAAA,uEAI7C,OAAW,0BA4EL,MA3EN,GA2EM,0BAbE,MAAA,CA5DJ,OAAA,EAAA,EAAA,gBAAK,CAAC,sBAAqB,CAAA,cAAA,CACD,EAAA,MAAe,CAAA,CAAA,CAAA,CAAA,CAE5B,EAAA,MAAY,OAAM,IAAA,EAAA,EAAA,YAAA,EAAA,EAAA,EAAA,oBA8CvB,QA9CR,GA8CQ,EAAA,EAAA,EAAA,oBA5BE,QAAA,KAAA,EAAA,EAAA,EAAA,oBADD,KAAA,KAAA,CAAA,AAAA,EAAA,MAAA,EAAA,EAAA,oBAd2B,KAAA,CAA1B,MAAM,aAAY,CAAC,KAAE,GAAA,GAAA,EAAA,EAAA,WAAA,GAAA,EAAA,EAAA,EAAA,oBAapB,EAAA,SAAA,MAAA,EAAA,EAAA,YAXoB,EAAA,OAAf,EAAK,gDAWV,KAAA,CAVF,IAAK,EAAI,IACV,MAAM,eACL,OAAA,EAAA,EAAA,gBAAK,CAAA,SAAc,EAAI,MAAK,KAAA,CAAA,4BAOvB,MALN,GAKM,EAAA,EAAA,EAAA,oBAFK,OAFT,IAAA,EAAA,EAAA,kBAAA,EAAA,EAAA,OACE,EAAe,CAAC,EAAK,CAAA,CAAA,EAAA,EAAA,EAAA,EAAA,oBAE0B,OAAjD,IAAA,EAAA,EAAA,iBAA8B,EAAI,MAAK,CAAA,EAAA,CAAA,CAAA,CAAA,CAAA,EAAA,sCA+BvC,QAAA,KAAA,GAAA,EAAA,EAAA,WAAA,GAAA,EAAA,EAAA,EAAA,oBADD,EAAA,SAAA,MAAA,EAAA,EAAA,YAvBuB,EAAA,OAAlB,EAAK,gDAuBV,KAAA,CAtBF,IAAK,EACN,MAAM,uCAID,KAFL,IAAA,EAAA,EAAA,kBACM,EAAA,MAAgB,GAAQ,EAAA,MAAW,EAAQ,EAAA,CAAA,EAAA,GAAA,EAAA,EAAA,WAAA,GAAA,EAAA,EAAA,EAAA,oBAiB5C,EAAA,SAAA,MAAA,EAAA,EAAA,YAdW,EAAA,MAAP,oEAcJ,KAAA,CAbF,IAAK,EAAI,IAEV,OAAA,EAAA,EAAA,gBAAK,CAAC,aAAY,aACY,EAAY,CAAC,EAAI,EAAI,MAAM,MAAK,CAAuB,EAAI,EAAI,MAAM,OAAM,cAAA,GAA4C,EAAA,MAAe,GAAA,kBAKnK,QAAS,EAAI,EAAI,MAAM,SAAO,EAC9B,QAAS,EAAI,EAAI,MAAM,SAAO,EAC9B,MAAO,EAAI,EAAI,MAAM,yCAEnB,EAAe,CAAC,EAAI,EAAI,MAAM,MAAK,CAAA,CAAA,GAAA,GAAA,EAAA,CAAA,CAAA,EAAA,MAAA,CAX7B,EAAI,EAAI,MAAM,OAAM,CAAA,CAAA,mEAyB/B,MARN,GAQM,EAAA,EAAA,EAAA,cAAA,EAAA,EAAA,OADK,EAAA,OAAA,CAAA,CAND,YAAY,gBAAe,CAAA,CACtB,OAAA,EAAA,EAAA,aAGC,EAAA,EAAA,EAAA,cAAA,EAAA,EAAA,OAAA,EAAA,QAAA,CAAA,CAFD,KAAK,QAAS,QAAK,AAAA,EAAA,KAAA,GAAEC,EAAAA,MAAK,SAAA,6BAEnC,AAAA,EAAA,KAAA,EAAA,EAAA,EAAA,iBAF+C,SAE/C,GAAA,CAAA,CAAA,sDAMR,OAAW,CACA,EAAA,MAAe,IAAA,EAAA,EAAA,YAAA,EAAA,EAAA,EAAA,oBASpB,MATN,GASM,EAAA,EAAA,EAAA,cAAA,EAAA,EAAA,OADF,EAAA,YAAA,CAAA,CANQ,KAAM,EAAA,gCAAA,EAAgB,MAAA,EAC7B,aAAY,EAAA,MACZ,YAAW,EAAA,MACZ,mBAAA,GACC,cAAA,EAAA,EAAA,OAAY,EAAiB,CAC7B,oBAAkB,4JChG/B,SAAgB,EACd,EACA,EAIA,CACA,GAAM,CAAE,OAAM,MAAK,YAAa,EAG1B,GAAA,EAAA,EAAA,KAAc,GAAM,CACpB,GAAA,EAAA,EAAA,KAAY,GAAG,CACf,GAAA,EAAA,EAAA,KAAe,EAAE,CACjB,GAAA,EAAA,EAAA,KAAgB,GAAM,CAGtB,GAAA,EAAA,EAAA,KAAa,GAAG,CAChB,GAAA,EAAA,EAAA,KAAoB,EAAE,CAEtB,GAAA,EAAA,EAAA,KAAkB,GAAG,CACrB,GAAA,EAAA,EAAA,KAAiC,EAAE,CAAC,CAEpC,GAAA,EAAA,EAAA,KAAgC,EAAE,CAAC,CAGnC,GAAA,EAAA,EAAA,cACA,EAAS,OAAS,EAAS,QAAU,OAAe,EAAS,MAC7D,EAAK,OAAO,KAAa,EAAK,MAAM,KACpC,EAAI,MAAc,EAAuB,EAAI,MAAM,CAChD,OACP,CAEI,GAAA,EAAA,EAAA,cACJ,EAAY,EAAgB,MAAM,CACnC,CACK,GAAA,EAAA,EAAA,cAA4B,EAAc,EAAS,MAAM,CAAC,CAG1D,MAAmB,CACvB,EAAM,MAAQ,GACd,EAAQ,MAAQ,GAChB,EAAO,MAAQ,GACf,EAAc,MAAQ,EACtB,EAAY,MAAQ,GACpB,EAAa,MAAQ,EAAE,CACvB,EAAY,MAAQ,EAAE,EAGlB,EAAY,GAAgB,CAChC,EAAM,MAAQ,EACd,EAAQ,MAAQ,IAIZ,EAAc,SAA2B,CAC7C,GAAI,EAAK,MAEP,MADA,GAAS,MAAQ,EAAK,MAAM,KACrB,EAAK,MAEd,GAAI,EAAI,MAAO,CACb,IAAM,EAAW,MAAM,MAAM,EAAI,MAAM,CACvC,GAAI,CAAC,EAAS,GACZ,MAAU,MAAM,QAAQ,EAAS,OAAO,IAAI,EAAS,aAAa,CAEpE,IAAM,EAAO,MAAM,EAAS,MAAM,CAC5B,EAAW,IAAI,KAAK,CAAC,EAAK,CAAE,EAAgB,MAAO,CACvD,KAAM,EAAK,KACZ,CAAC,CAEF,MADA,GAAS,MAAQ,EAAS,KACnB,EAET,MAAU,MAAM,YAAY,EAGxB,EAAa,MACjB,EACA,IACkB,CAClB,OAAQ,EAAR,CACE,IAAK,MAAO,CACV,IAAM,EAAS,MAAM,EAAQ,EAAY,CACzC,EAAO,MAAQ,EAAO,IACtB,EAAc,MAAQ,EAAO,WAC7B,MAEF,IAAK,OAAQ,CACX,IAAM,EAAS,MAAM,EAAS,EAAY,CAC1C,EAAY,MAAQ,EAAO,QAC3B,EAAa,MAAQ,EAAO,SAC5B,MAEF,IAAK,QAEH,EAAY,OADG,MAAM,EAAU,EAAY,EAChB,OAC3B,MAEF,QACE,MAAU,MAAM,WAAW,GAK3B,EAAW,SAAY,CAC3B,GAAI,CAAC,EAAK,OAAS,CAAC,EAAI,MAAO,CAC7B,EAAS,YAAY,CACrB,OAGF,GAAY,CACZ,EAAQ,MAAQ,GAEhB,GAAI,CAEF,MAAM,EADc,MAAM,GAAa,CACT,EAAS,MAAM,CAC7C,EAAQ,MAAQ,SACT,EAAK,CACZ,IAAM,EAAe,aAAe,MAAQ,EAAI,QAAU,OAC1D,EAAS,GAAG,EAAS,MAAM,aAAa,CAAC,UAAU,IAAe,GAwCtE,OAdA,EAAA,EAAA,WACQ,EAAK,OAAO,KACjB,GAAY,CACX,EAAS,MAAQ,GAAW,GAE9B,CAAE,UAAW,GAAM,CACpB,EAED,EAAA,EAAA,iBAAkB,CACZ,EAAO,OAAO,WAAW,QAAQ,EACnC,IAAI,gBAAgB,EAAO,MAAM,MAAM,IAAI,CAAC,GAAG,EAEjD,CAEK,CAEL,UACA,QACA,WACA,YAEA,SACA,gBACA,cACA,eACA,cAEA,kBACA,WACA,aAEA,WACA,YAtDkB,SAAY,CAC9B,EAAU,MAAQ,GAClB,MAAM,GAAU,CAChB,EAAK,UAAW,EAAK,OAAS,EAAI,MAAO,EAoDzC,iBAjDyB,CACzB,GAAI,EAAK,MAAO,CACd,IAAM,EAAc,IAAI,gBAAgB,EAAK,MAAM,CACzC,OAAO,OAAO,SAAS,cAAc,IAAI,CAAE,CACnD,KAAM,EACN,SAAU,EAAgB,MAC3B,CAAC,CACA,OAAO,CACT,IAAI,gBAAgB,EAAY,MACvB,EAAI,OACb,OAAO,KAAK,EAAI,MAAO,SAAS,CAElC,EAAK,WAAY,EAAK,OAAS,EAAI,MAAO,EAsC3C,CCjMH,SAAgB,EAAc,EAA4C,CACxE,IAAM,GAAA,EAAA,EAAA,KAAmB,GAAM,CAEzB,MAA+B,CACnC,EAAa,MAAQ,CAAC,CAAC,SAAS,mBAG5B,GACJ,EACA,EAAQ,IAEJ,GAAS,EAAQ,QACnB,QAAQ,KAAK,WAAW,CACjB,QAAQ,SAAS,EAEnB,EAAQ,IAAQ,CAAC,UAAY,EAAW,EAAS,EAAQ,EAAE,CAAC,CAiDrE,OAZA,EAAA,EAAA,eAAgB,CACd,EAAkB,QAAS,GACzB,SAAS,iBAAiB,EAAO,EAAuB,CACzD,EACD,EAEF,EAAA,EAAA,iBAAkB,CAChB,EAAkB,QAAS,GACzB,SAAS,oBAAoB,EAAO,EAAuB,CAC5D,EACD,CAEK,CAAE,eAAc,iBA9CE,SAAY,CACnC,IAAM,EAAU,EAAa,MACxB,GAkBL,MAAM,EAhB0B,SAAS,kBAGrC,KACQ,SAAS,gBAAgB,KACxB,SAAiB,sBAAsB,KACvC,SAAiB,qBAAqB,KACtC,SAAiB,kBAAkB,CAC3C,CACD,KACQ,EAAQ,mBAAmB,KAC1B,EAAgB,yBAAyB,KACzC,EAAgB,sBAAsB,KACtC,EAAgB,qBAAqB,CAC7C,CAEoB,EA0Bc,eAvBlB,SAAY,CACjC,GAAI,SAAS,kBACX,GAAI,CACF,MAAM,SAAS,gBAAgB,MACzB,EAIV,EAAa,MAAQ,IAekC,4wBC0LzD,GAAM,CAAE,OAAM,MAAK,SAAU,EAAc,gBAAA,EAAA,EAAA,QAb7B,EAayD,CAQjE,CACJ,UACA,QACA,WACA,YACA,SACA,gBACA,cACA,eACA,cACA,kBACA,WACA,aACA,WACA,cACA,gBACE,EAAe,CAAE,OAAM,MAAK,SAAU,EAAc,CAtB3C,EAsBiD,CAExD,GAAA,EAAA,EAAA,MAAkC,CAClC,CAAE,eAAc,mBAAkB,kBACtC,EAAc,EAAc,QAG9B,EAAA,EAAA,OAAM,EAAW,GAAU,CACpB,GAAQ,GAAe,EAC7B,oEC7DK,MA/NN,GA+NM,0BA9NJ,aAAiB,aAER,EAAW,uCAAA,EAAA,EAAA,YAAA,EAAA,EAAA,EAAA,oBAoDd,MArDN,GAqDM,EAAA,EAAA,EAAA,oBADE,MAhDN,GAgDM,0BAzCE,MANN,GAMM,EAAA,EAAA,EAAA,aADF,EAAA,CAHC,MAAA,EAAA,EAAA,OAAM,EAAU,CAAC,KACjB,KAAM,GACN,OAAA,EAAA,EAAA,OAAO,EAAU,CAAC,2DAoBjB,MAhBN,GAgBM,EAAA,EAAA,EAAA,oBALE,MAVN,GAUM,EAAA,EAAA,EAAA,cAAA,EAAA,EAAA,OAPU,EAAA,UAAA,CAAA,CAFH,MAAA,CAAA,YAAA,QAAwB,CAAA,CAAA,2BAEjC,EAAA,EAAA,EAAA,kBAAA,EAAA,EAAA,kBAAA,EAAA,EAAA,OADA,EAAe,CAAA,CAAA,EAAA,CAAA,CAAA,qCAOV,EAAA,KAAA,CAAA,CAJJ,MAAA,EAAA,EAAA,OAAM,EAAU,CAAC,QAClB,KAAK,oCAEuB,EAAA,EAAA,EAAA,kBAAA,EAAA,EAAA,kBAAA,EAAA,EAAA,OAAzB,EAAQ,CAAC,aAAW,CAAA,CAAA,EAAA,CAAA,CAAA,6CAMrB,MAFN,GAEM,EAAA,EAAA,EAAA,oBADyD,OAA7D,IAAA,EAAA,EAAA,kBAAA,EAAA,EAAA,OAA2B,EAAc,EAAA,EAAA,EAAA,OAAC,EAAQ,CAAA,CAAA,CAAA,EAAA,CAAA,CAAA,CAAA,CAAA,0BAwBhD,MApBN,GAoBM,EAAA,EAAA,EAAA,cAAA,EAAA,EAAA,OAXM,EAAA,QAAA,CAAA,CAPR,KAAK,UACJ,SAAA,EAAA,EAAA,OAAO,EAAA,GAEG,MAAA,EAAA,EAAA,aAC8B,EAAA,EAAA,EAAA,aAAA,EAAA,CAA/B,KAAK,wBAAuB,CAAA,CAAA,CAAA,2BAGxC,CAAA,AAAA,EAAA,MAAA,EAAA,EAAA,iBAFa,OAEb,GAAA,CAAA,CAAA,0DAUU,EAAA,QAAA,CAAA,CAPR,KAAK,WACJ,SAAA,EAAA,EAAA,OAAO,EAAA,GAEG,MAAA,EAAA,EAAA,aAC4B,EAAA,EAAA,EAAA,aAAA,EAAA,CAA7B,KAAK,sBAAqB,CAAA,CAAA,CAAA,2BAGtC,CAAA,AAAA,EAAA,MAAA,EAAA,EAAA,iBAFa,OAEb,GAAA,CAAA,CAAA,4DAKN,UAAc,+BAqKL,EAAA,OAAA,CAAA,CAnKC,MAAA,EAAA,EAAA,OAAM,EAAS,0CAAT,EAAS,MAAA,EAAA,KACtB,gBAAe,GACf,SAAU,GACV,aAAY,GACb,mBAAiB,SACjB,MAAA,CAAA,MAAA,OAAA,YAAA,SAAA,YAAA,QAAA,OAAA,OAAA,aAAA,QAAA,aAAA,qCA6JM,EAAA,EAAA,EAAA,oBAAA,MAAA,SAnJA,iBAAJ,IAAI,EACJ,MAAM,6CAEN,UAAc,0BA+BR,MA9BN,GA8BM,EAAA,EAAA,EAAA,oBAtBE,MAPN,GAOM,EAAA,EAAA,EAAA,aAFF,EAAA,CAHC,MAAA,EAAA,EAAA,OAAM,EAAU,CAAC,KACjB,KAAM,GACN,OAAA,EAAA,EAAA,OAAO,EAAU,CAAC,yDAEa,OAAA,MAAA,EAAA,EAAA,kBAAA,EAAA,EAAA,OAAzB,EAAe,CAAA,CAAA,EAAA,CAAA,CAAA,EAAA,EAAA,EAAA,oBAsBpB,MApBN,GAoBM,EAAA,EAAA,EAAA,cAAA,EAAA,EAAA,OAVM,EAAA,QAAA,CAAA,CARR,KAAK,QACL,KAAK,WACJ,SAAA,EAAA,EAAA,OAAO,EAAA,GAEG,MAAA,EAAA,EAAA,aAC4B,EAAA,EAAA,EAAA,aAAA,EAAA,CAA7B,KAAK,sBAAqB,CAAA,CAAA,CAAA,2BAGtC,CAAA,AAAA,EAAA,MAAA,EAAA,EAAA,iBAFa,OAEb,GAAA,CAAA,CAAA,0DASU,EAAA,QAAA,CAAA,CAPR,KAAK,QACL,KAAK,WACJ,QAAK,AAAA,EAAA,KAAA,GAAE,EAAA,MAAS,KAEN,MAAA,EAAA,EAAA,aACyB,EAAA,EAAA,EAAA,aAAA,EAAA,CAA1B,KAAK,mBAAkB,CAAA,CAAA,CAAA,oCAMvC,SAAa,0BA8GP,MA7GN,EA6GM,0BA5GJ,WAAe,0BAmDT,MAlDN,GAkDM,EAAA,EAAA,EAAA,oBADE,MAhDN,GAgDM,EAAA,EAAA,EAAA,oBA/BE,MAhBN,GAgBM,+BAPG,EAAA,KAAA,CAAA,CAPJ,MAAA,EAAA,EAAA,OAAM,EAAU,CAAC,QAClB,KAAK,UAEM,MAAA,EAAA,EAAA,aACyB,EAAA,EAAA,EAAA,aAAA,EAAA,CAAzB,MAAA,EAAA,EAAA,OAAM,EAAU,CAAC,KAAA,CAAA,KAAA,EAAA,CAAA,OAAA,CAAA,CAAA,CAAA,2BAE5B,EAAA,EAAA,EAAA,iBADW,KAAA,EAAA,EAAA,kBAAA,EAAA,EAAA,OACR,EAAQ,CAAC,aAAW,CAAA,CAAA,EAAA,CAAA,CAAA,gDAIX,EAAA,UAAA,CAAA,CAFH,MAAA,CAAA,YAAA,QAAwB,CAAA,CAAA,2BAEjC,EAAA,EAAA,EAAA,kBAAA,EAAA,EAAA,kBAAA,EAAA,EAAA,OADA,EAAe,CAAA,CAAA,EAAA,CAAA,CAAA,gCAIR,OAFT,IAAA,EAAA,EAAA,kBAAA,EAAA,EAAA,OACE,EAAc,EAAA,EAAA,EAAA,OAAC,EAAQ,CAAA,CAAA,CAAA,EAAA,4BAgCrB,MA5BN,GA4BM,EAAA,EAAA,EAAA,cAAA,EAAA,EAAA,OAjBM,EAAA,QAAA,CAAA,CATR,KAAK,QACL,KAAK,WACJ,UAAA,EAAA,EAAA,OAAU,EAAO,CACjB,SAAA,EAAA,EAAA,OAAO,EAAA,GAEG,MAAA,EAAA,EAAA,aAC2B,EAAA,EAAA,EAAA,aAAA,EAAA,CAA5B,KAAK,qBAAoB,CAAA,CAAA,CAAA,2BAGrC,CAAA,AAAA,EAAA,MAAA,EAAA,EAAA,iBAFa,OAEb,GAAA,CAAA,CAAA,qEAgBU,EAAA,QAAA,CAAA,CAdR,KAAK,QACL,KAAK,UACJ,SAAA,EAAA,EAAA,OAAO,EAAA,GAEG,MAAA,EAAA,EAAA,aAOP,EAAA,EAAA,EAAA,aAAA,EAAA,CALC,MAAA,EAAA,EAAA,OAA+B,EAAY,CAAA,6BAAA,wBAAA,CAAA,KAAA,EAAA,CAAA,OAAA,CAAA,CAAA,CAAA,2BAOhD,EAAA,EAAA,EAAA,iBADW,KAAA,EAAA,EAAA,kBAAA,EAAA,EAAA,OACR,EAAY,CAAA,OAAA,KAAA,CAAA,EAAA,CAAA,CAAA,oDAMvB,WAAe,0BAsDT,MArDN,GAqDM,EAAA,EAAA,EAAA,oBApDJ,YAAgB,EAAA,EAAA,EAAA,OACA,EAAO,GAAA,EAAA,EAAA,OAAI,EAAK,GAAA,EAAA,EAAA,YAAA,EAAA,EAAA,EAAA,oBAoBxB,MAnBN,GAmBM,EAAA,EAAA,EAAA,OAjBI,EAAO,GAAA,EAAA,EAAA,YAAA,EAAA,EAAA,EAAA,cAAA,EAAA,EAAA,OAMP,EAAA,MAAA,CAAA,OALN,KAAK,UAEM,aAAA,EAAA,EAAA,aACL,EAAA,EAAA,EAAA,iBADiB,SAAA,EAAA,EAAA,kBAAA,EAAA,EAAA,OACd,EAAQ,CAAC,aAAW,CAAA,CAAK,SAClC,EAAA,CAAA,CAAA,yDAWQ,EAAA,QAAA,CAAA,OAPR,OAAO,QACP,MAAM,OACL,aAAA,EAAA,EAAA,OAAa,EAAA,GAEH,QAAA,EAAA,EAAA,aAC8B,EAAA,EAAA,EAAA,cAAA,EAAA,EAAA,OAAA,EAAA,QAAA,CAAA,CAA7B,SAAA,EAAA,EAAA,OAAO,EAAQ,CAAA,CAAA,2BAAI,AAAA,EAAA,KAAA,EAAA,EAAA,EAAA,iBAAF,KAAE,GAAA,CAAA,CAAA,sGAiC1B,EAAA,SAAA,CAAA,IAAA,EAAA,CAAA,EAAA,EAAA,EAAA,oBA3BX,kBAAsB,EAAA,EAAA,EAAA,OAGZ,EAAQ,GAAA,QAAA,EAAA,EAAA,YAAA,EAAA,EAAA,EAAA,aAGd,EAAA,OAFC,WAAA,EAAA,EAAA,OAAS,EAAM,CACf,eAAA,EAAA,EAAA,OAAa,EAAA,iDAIH,EAAQ,GAAA,SAAA,EAAA,EAAA,YAAA,EAAA,EAAA,EAAA,aAGnB,EAAA,OAFC,SAAA,EAAA,EAAA,OAAS,EAAW,CACpB,UAAA,EAAA,EAAA,OAAU,EAAA,8CAIA,EAAQ,GAAA,UAAA,EAAA,EAAA,YAAA,EAAA,EAAA,EAAA,aAGnB,GAAA,OAFC,QAAA,EAAA,EAAA,OAAQ,EAAW,CACnB,UAAA,EAAA,EAAA,OAAQ,EAAA,6EAST,EAAA,SAAA,CAAA,IAAA,EAAA,CAAA,EAAA,EAAA,EAAA,oBANF,aAAiB,EAAA,EAAA,EAAA,cAAA,EAAA,EAAA,OAMf,EAAA,QAAA,CAAA,CAHA,OAAO,UACP,MAAM,WACL,YAAW,WAAA,EAAA,EAAA,OAAY,EAAQ,CAAC,aAAW,CAAA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"C_FilePreview2.js","names":["totalPages","pdfUrl","headings","content","sheets","$emit"],"sources":["../src/components/C_FilePreview/data.ts","../src/components/C_FilePreview/components/PdfViewer/index.vue","../src/components/C_FilePreview/components/PdfViewer/index.vue","../src/components/C_FilePreview/components/WordViewer/index.vue","../src/components/C_FilePreview/components/WordViewer/index.vue","../src/components/C_FilePreview/components/ExcelViewer/index.vue","../src/components/C_FilePreview/components/ExcelViewer/index.vue","../src/components/C_FilePreview/composables/useFilePreview.ts","../src/components/C_FilePreview/composables/useFullscreen.ts","../src/components/C_FilePreview/index.vue","../src/components/C_FilePreview/index.vue"],"sourcesContent":["/**\r\n * C_FilePreview 常量配置与工具函数\r\n * 类型定义统一在 ./types.ts\r\n */\r\nimport { type Ref } from \"vue\";\r\nimport * as XLSX from \"xlsx\";\r\nimport mammoth from \"mammoth\";\r\nimport type {\r\n FilePreviewType,\r\n FileConfig,\r\n ZoomConfig,\r\n ExcelRow,\r\n ExcelColumn,\r\n ExcelSheet,\r\n DocHeading,\r\n PdfLoadResult,\r\n WordLoadResult,\r\n ExcelLoadResult,\r\n} from \"./types\";\r\n\r\n/* ==================== 常量配置 ==================== */\r\n\r\nexport const FILE_TYPE_MAP: Record<string, FilePreviewType> = {\r\n pdf: \"pdf\",\r\n doc: \"word\",\r\n docx: \"word\",\r\n xls: \"excel\",\r\n xlsx: \"excel\",\r\n};\r\n\r\nexport const FILE_CONFIGS: Record<string, FileConfig> = {\r\n pdf: {\r\n tagType: \"error\",\r\n icon: \"ic:outline-picture-as-pdf\",\r\n color: \"#dc2626\",\r\n },\r\n word: { tagType: \"info\", icon: \"ic:outline-description\", color: \"#2563eb\" },\r\n excel: { tagType: \"success\", icon: \"ic:outline-grid-on\", color: \"#16a34a\" },\r\n unknown: {\r\n tagType: \"default\",\r\n icon: \"ic:outline-insert-drive-file\",\r\n color: \"#6b7280\",\r\n },\r\n};\r\n\r\nexport const ZOOM_CONFIGS: Record<string, ZoomConfig> = {\r\n pdf: { min: 0.5, max: 3, step: 0.25, default: 1 },\r\n word: { min: 50, max: 200, step: 10, default: 100 },\r\n};\r\n\r\nexport const PAGE_SIZE_OPTIONS = [20, 50, 100, 200];\r\n\r\nexport const FULLSCREEN_EVENTS = [\r\n \"fullscreenchange\",\r\n \"webkitfullscreenchange\",\r\n \"mozfullscreenchange\",\r\n \"MSFullscreenChange\",\r\n];\r\n\r\n/* ==================== 文件信息工具函数 ==================== */\r\n\r\nexport const extractFileNameFromUrl = (url: string): string => {\r\n try {\r\n const urlPath = url.split(\"/\").pop() || url.split(\"\\\\\").pop();\r\n if (urlPath?.includes(\".\")) {\r\n const decodedName = decodeURIComponent(urlPath.split(\"?\")[0]);\r\n if (decodedName && decodedName !== url) return decodedName;\r\n }\r\n } catch (error) {\r\n console.warn(\"解析URL文件名失败:\", error);\r\n }\r\n return \"未知文件\";\r\n};\r\n\r\nexport const formatFileSize = (bytes: number): string => {\r\n if (bytes === 0) return \"0 B\";\r\n const k = 1024;\r\n const sizes = [\"B\", \"KB\", \"MB\", \"GB\"];\r\n const i = Math.floor(Math.log(bytes) / Math.log(k));\r\n return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + \" \" + sizes[i];\r\n};\r\n\r\nexport const getFileType = (fileName: string): FilePreviewType => {\r\n if (!fileName || fileName === \"未知文件\") return \"unknown\";\r\n const ext = fileName.toLowerCase().split(\".\").pop();\r\n if (!ext) return \"unknown\";\r\n return FILE_TYPE_MAP[ext] || \"unknown\";\r\n};\r\n\r\nexport const getFileConfig = (fileType: string): FileConfig => {\r\n return FILE_CONFIGS[fileType] || FILE_CONFIGS.unknown;\r\n};\r\n\r\n/* ==================== 缩放工具 ==================== */\r\n\r\nexport const createZoomHandler = (\r\n valueRef: Ref<number>,\r\n config: ZoomConfig,\r\n) => {\r\n return (action: \"in\" | \"out\" | \"reset\") => {\r\n const { min, max, step, default: defaultValue } = config;\r\n switch (action) {\r\n case \"reset\":\r\n valueRef.value = defaultValue;\r\n break;\r\n case \"in\":\r\n if (valueRef.value < max) valueRef.value += step;\r\n break;\r\n case \"out\":\r\n if (valueRef.value > min) valueRef.value -= step;\r\n break;\r\n }\r\n };\r\n};\r\n\r\n/* ==================== Excel 工具函数 ==================== */\r\n\r\nexport const getColumnLetter = (index: number): string => {\r\n let result = \"\";\r\n while (index >= 0) {\r\n result = String.fromCharCode(65 + (index % 26)) + result;\r\n index = Math.floor(index / 26) - 1;\r\n }\r\n return result;\r\n};\r\n\r\nexport const formatCellValue = (value: any): string => {\r\n if (!value) return \"\";\r\n const strValue = String(value).trim();\r\n\r\n if (!isNaN(Number(strValue)) && strValue !== \"\" && strValue.length < 15) {\r\n const num = Number(strValue);\r\n return Number.isInteger(num)\r\n ? num.toLocaleString()\r\n : num.toLocaleString(undefined, { maximumFractionDigits: 2 });\r\n }\r\n return strValue;\r\n};\r\n\r\nexport const getCellClass = (value: any): string => {\r\n if (!value) return \"cell-empty\";\r\n const strValue = String(value).trim();\r\n\r\n if (!isNaN(Number(strValue)) && strValue !== \"\") return \"cell-number\";\r\n if (strValue.match(/[■▬▪▫─━]/)) return \"cell-gantt\";\r\n if (\r\n strValue.match(/^\\d{4}[-/]\\d{2}[-/]\\d{2}/) ||\r\n strValue.match(/^\\d{2}[-/]\\d{2}[-/]\\d{4}/)\r\n )\r\n return \"cell-date\";\r\n if ([\"true\", \"false\"].includes(strValue.toLowerCase())) return \"cell-boolean\";\r\n return strValue.length > 20 ? \"cell-text cell-long\" : \"cell-text\";\r\n};\r\n\r\nexport const processExcelSheet = (\r\n worksheet: any,\r\n merges: any[],\r\n): { data: ExcelRow[]; columns: ExcelColumn[] } => {\r\n const range = XLSX.utils.decode_range(worksheet[\"!ref\"] || \"A1:A1\");\r\n const { c: maxCol, r: maxRow } = range.e;\r\n\r\n const columns: ExcelColumn[] = Array.from({ length: maxCol + 1 }, (_, c) => {\r\n const cellAddress = XLSX.utils.encode_cell({ r: 0, c });\r\n const cell = worksheet[cellAddress];\r\n const columnName = cell ? String(cell.v || \"\").trim() : `列${c + 1}`;\r\n return {\r\n title: columnName || `列${c + 1}`,\r\n key: `col_${c}`,\r\n width: Math.min(Math.max(columnName.length * 12, 80), 200),\r\n };\r\n });\r\n\r\n const mergeMap = new Map();\r\n merges.forEach(({ s: { r: sRow, c: sCol }, e: { r: eRow, c: eCol } }) => {\r\n for (let r = sRow; r <= eRow; r++) {\r\n for (let c = sCol; c <= eCol; c++) {\r\n mergeMap.set(`${r}-${c}`, {\r\n isMain: r === sRow && c === sCol,\r\n rowspan: eRow - sRow + 1,\r\n colspan: eCol - sCol + 1,\r\n });\r\n }\r\n }\r\n });\r\n\r\n const data: ExcelRow[] = Array.from({ length: maxRow + 1 }, (_, r) => {\r\n const row: ExcelRow = {};\r\n for (let c = 0; c <= maxCol; c++) {\r\n const cellAddress = XLSX.utils.encode_cell({ r, c });\r\n const cell = worksheet[cellAddress];\r\n const mergeInfo = mergeMap.get(`${r}-${c}`);\r\n\r\n row[`col_${c}`] = {\r\n value: cell ? cell.v || \"\" : \"\",\r\n merged: !!mergeInfo,\r\n hidden: mergeInfo && !mergeInfo.isMain,\r\n rowspan: mergeInfo?.isMain ? mergeInfo.rowspan : 1,\r\n colspan: mergeInfo?.isMain ? mergeInfo.colspan : 1,\r\n };\r\n }\r\n return row;\r\n });\r\n\r\n return { data, columns };\r\n};\r\n\r\n/* ==================== 文件加载器 ==================== */\r\n\r\nexport async function loadPdf(file: File): Promise<PdfLoadResult> {\r\n const fileUrl = URL.createObjectURL(file);\r\n return {\r\n url: fileUrl + \"#toolbar=1&navpanes=1&scrollbar=1&view=FitH\",\r\n totalPages: 1,\r\n };\r\n}\r\n\r\nexport async function loadWord(file: File): Promise<WordLoadResult> {\r\n const arrayBuffer = await file.arrayBuffer();\r\n const result = await mammoth.convertToHtml({\r\n arrayBuffer,\r\n styleMap: [\r\n \"p[style-name='Heading 1'] => h1:fresh\",\r\n \"p[style-name='Heading 2'] => h2:fresh\",\r\n \"p[style-name='Heading 3'] => h3:fresh\",\r\n \"p[style-name='Title'] => h1.title:fresh\",\r\n ],\r\n } as any);\r\n\r\n let content = result.value;\r\n const headings: DocHeading[] = [];\r\n\r\n /* 提取标题并注入 id */\r\n const tempDiv = document.createElement(\"div\");\r\n tempDiv.innerHTML = content;\r\n const headingElements = tempDiv.querySelectorAll(\"h1, h2, h3, h4, h5, h6\");\r\n\r\n Array.from(headingElements).forEach((el, index) => {\r\n const id = `heading-${index}`;\r\n const level = parseInt(el.tagName.charAt(1));\r\n const text = el.textContent || \"\";\r\n\r\n content = content.replace(\r\n el.outerHTML,\r\n el.outerHTML.replace(\r\n el.tagName.toLowerCase(),\r\n `${el.tagName.toLowerCase()} id=\"${id}\"`,\r\n ),\r\n );\r\n\r\n headings.push({ id, text, level });\r\n });\r\n\r\n return { content, headings };\r\n}\r\n\r\nexport async function loadExcel(file: File): Promise<ExcelLoadResult> {\r\n const arrayBuffer = await file.arrayBuffer();\r\n const workbook = XLSX.read(arrayBuffer, {\r\n type: \"array\",\r\n cellStyles: true,\r\n cellFormula: true,\r\n cellDates: true,\r\n });\r\n\r\n if (!workbook.SheetNames.length) {\r\n throw new Error(\"Excel文件中没有找到工作表\");\r\n }\r\n\r\n const sheets: ExcelSheet[] = workbook.SheetNames.map((name) => {\r\n const worksheet = workbook.Sheets[name];\r\n const merges = worksheet[\"!merges\"] || [];\r\n const { data, columns } = processExcelSheet(worksheet, merges);\r\n return { name, data, merges, columns };\r\n });\r\n\r\n return { sheets };\r\n}\r\n","<!--\n PdfViewer — PDF 文件预览子组件\n 负责: 工具栏(翻页+缩放) + iframe 渲染\n-->\n<template>\n <div class=\"file-container pdf-container\">\n <div class=\"file-toolbar\">\n <div class=\"flex justify-between items-center\">\n <!-- 翻页控制 -->\n <div class=\"flex gap-2 items-center\">\n <NButton\n size=\"small\"\n :disabled=\"currentPage <= 1\"\n @click=\"changePage('prev')\"\n >\n <template #icon>\n <C_Icon name=\"ic:outline-chevron-left\" />\n </template>\n </NButton>\n <NInputNumber\n v-model:value=\"currentPage\"\n size=\"small\"\n :min=\"1\"\n :max=\"totalPages\"\n style=\"width: 80px\"\n @update:value=\"changePage as any\"\n />\n <span class=\"text-sm text-gray-600\">/ {{ totalPages }}</span>\n <NButton\n size=\"small\"\n :disabled=\"currentPage >= totalPages\"\n @click=\"changePage('next')\"\n >\n <template #icon>\n <C_Icon name=\"ic:outline-chevron-right\" />\n </template>\n </NButton>\n </div>\n\n <!-- 缩放控制 -->\n <div class=\"flex gap-2 items-center\">\n <NButton\n size=\"small\"\n :disabled=\"scale <= 0.5\"\n @click=\"adjustZoom('out')\"\n >\n <template #icon>\n <C_Icon name=\"ic:outline-zoom-out\" />\n </template>\n </NButton>\n <span class=\"text-sm text-gray-600 min-w-12 text-center\">\n {{ Math.round(scale * 100) }}%\n </span>\n <NButton\n size=\"small\"\n :disabled=\"scale >= 3\"\n @click=\"adjustZoom('in')\"\n >\n <template #icon>\n <C_Icon name=\"ic:outline-zoom-in\" />\n </template>\n </NButton>\n <NButton\n size=\"small\"\n @click=\"adjustZoom('reset')\"\n >\n <template #icon>\n <C_Icon name=\"ic:outline-fit-screen\" />\n </template>\n 适应\n </NButton>\n </div>\n </div>\n </div>\n\n <div class=\"file-viewer\">\n <iframe\n v-if=\"pdfUrl\"\n :src=\"pdfUrl\"\n class=\"w-full h-full border-0\"\n title=\"PDF预览\"\n frameborder=\"0\"\n allowfullscreen\n />\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\n import { ref } from 'vue'\n import { NButton, NInputNumber } from 'naive-ui'\n import { createZoomHandler, ZOOM_CONFIGS } from '../../data'\n\n const props = defineProps<{\n pdfUrl: string\n totalPages: number\n }>()\n\n const currentPage = ref(1)\n const scale = ref(1)\n\n const adjustZoom = createZoomHandler(scale, ZOOM_CONFIGS.pdf)\n\n const changePage = (action: 'prev' | 'next' | number) => {\n if (typeof action === 'number') {\n currentPage.value = Math.max(1, Math.min(action, props.totalPages))\n } else {\n const delta = action === 'prev' ? -1 : 1\n currentPage.value = Math.max(\n 1,\n Math.min(currentPage.value + delta, props.totalPages)\n )\n }\n }\n</script>\n\n<style lang=\"scss\" scoped>\n @use './index.scss';\n</style>\n","<!--\n PdfViewer — PDF 文件预览子组件\n 负责: 工具栏(翻页+缩放) + iframe 渲染\n-->\n<template>\n <div class=\"file-container pdf-container\">\n <div class=\"file-toolbar\">\n <div class=\"flex justify-between items-center\">\n <!-- 翻页控制 -->\n <div class=\"flex gap-2 items-center\">\n <NButton\n size=\"small\"\n :disabled=\"currentPage <= 1\"\n @click=\"changePage('prev')\"\n >\n <template #icon>\n <C_Icon name=\"ic:outline-chevron-left\" />\n </template>\n </NButton>\n <NInputNumber\n v-model:value=\"currentPage\"\n size=\"small\"\n :min=\"1\"\n :max=\"totalPages\"\n style=\"width: 80px\"\n @update:value=\"changePage as any\"\n />\n <span class=\"text-sm text-gray-600\">/ {{ totalPages }}</span>\n <NButton\n size=\"small\"\n :disabled=\"currentPage >= totalPages\"\n @click=\"changePage('next')\"\n >\n <template #icon>\n <C_Icon name=\"ic:outline-chevron-right\" />\n </template>\n </NButton>\n </div>\n\n <!-- 缩放控制 -->\n <div class=\"flex gap-2 items-center\">\n <NButton\n size=\"small\"\n :disabled=\"scale <= 0.5\"\n @click=\"adjustZoom('out')\"\n >\n <template #icon>\n <C_Icon name=\"ic:outline-zoom-out\" />\n </template>\n </NButton>\n <span class=\"text-sm text-gray-600 min-w-12 text-center\">\n {{ Math.round(scale * 100) }}%\n </span>\n <NButton\n size=\"small\"\n :disabled=\"scale >= 3\"\n @click=\"adjustZoom('in')\"\n >\n <template #icon>\n <C_Icon name=\"ic:outline-zoom-in\" />\n </template>\n </NButton>\n <NButton\n size=\"small\"\n @click=\"adjustZoom('reset')\"\n >\n <template #icon>\n <C_Icon name=\"ic:outline-fit-screen\" />\n </template>\n 适应\n </NButton>\n </div>\n </div>\n </div>\n\n <div class=\"file-viewer\">\n <iframe\n v-if=\"pdfUrl\"\n :src=\"pdfUrl\"\n class=\"w-full h-full border-0\"\n title=\"PDF预览\"\n frameborder=\"0\"\n allowfullscreen\n />\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\n import { ref } from 'vue'\n import { NButton, NInputNumber } from 'naive-ui'\n import { createZoomHandler, ZOOM_CONFIGS } from '../../data'\n\n const props = defineProps<{\n pdfUrl: string\n totalPages: number\n }>()\n\n const currentPage = ref(1)\n const scale = ref(1)\n\n const adjustZoom = createZoomHandler(scale, ZOOM_CONFIGS.pdf)\n\n const changePage = (action: 'prev' | 'next' | number) => {\n if (typeof action === 'number') {\n currentPage.value = Math.max(1, Math.min(action, props.totalPages))\n } else {\n const delta = action === 'prev' ? -1 : 1\n currentPage.value = Math.max(\n 1,\n Math.min(currentPage.value + delta, props.totalPages)\n )\n }\n }\n</script>\n\n<style lang=\"scss\" scoped>\n @use './index.scss';\n</style>\n","<!--\n WordViewer — Word 文档预览子组件\n 负责: 目录导航 + 缩放 + 文档内容渲染\n-->\n<template>\n <div class=\"file-container word-container\">\n <div class=\"file-toolbar\">\n <div class=\"flex gap-2 items-center\">\n <NButton size=\"small\" @click=\"showOutline = !showOutline\">\n <template #icon>\n <C_Icon name=\"ic:outline-list\" />\n </template>\n {{ showOutline ? \"隐藏\" : \"显示\" }}目录\n </NButton>\n <NDivider vertical />\n <NButton\n size=\"small\"\n :disabled=\"wordZoom <= 50\"\n @click=\"adjustWordZoom('out')\"\n >\n <template #icon>\n <C_Icon name=\"ic:outline-zoom-out\" />\n </template>\n </NButton>\n <span class=\"text-sm text-gray-600 min-w-12 text-center\">\n {{ wordZoom }}%\n </span>\n <NButton\n size=\"small\"\n :disabled=\"wordZoom >= 200\"\n @click=\"adjustWordZoom('in')\"\n >\n <template #icon>\n <C_Icon name=\"ic:outline-zoom-in\" />\n </template>\n </NButton>\n <NButton size=\"small\" @click=\"adjustWordZoom('reset')\">\n <template #icon>\n <C_Icon name=\"ic:outline-fit-screen\" />\n </template>\n 重置\n </NButton>\n </div>\n </div>\n\n <div class=\"word-layout\">\n <div class=\"word-main\">\n <!-- 侧边栏目录 -->\n <div v-if=\"showOutline\" class=\"word-outline\">\n <div class=\"outline-header\">\n <h3 class=\"text-sm font-semibold\">文档目录</h3>\n </div>\n <div class=\"outline-content\">\n <div\n v-for=\"(heading, index) in headings\"\n :key=\"index\"\n class=\"outline-item\"\n :class=\"`level-${heading.level}`\"\n @click=\"scrollToHeading(heading.id)\"\n >\n {{ heading.text }}\n </div>\n </div>\n </div>\n\n <!-- 主要内容区域 -->\n <div class=\"word-content\">\n <div\n class=\"word-document\"\n :style=\"{\n transform: `scale(${wordZoom / 100})`,\n transformOrigin: 'top center',\n }\"\n v-html=\"content\"\n ></div>\n </div>\n </div>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref } from \"vue\";\nimport { NButton, NDivider } from \"naive-ui\";\nimport { createZoomHandler, ZOOM_CONFIGS } from \"../../data\";\nimport type { DocHeading } from \"../../types\";\n\ndefineProps<{\n content: string;\n headings: DocHeading[];\n}>();\n\nconst showOutline = ref(true);\nconst wordZoom = ref(100);\n\nconst adjustWordZoom = createZoomHandler(wordZoom, ZOOM_CONFIGS.word);\n\nconst scrollToHeading = (headingId: string) => {\n document\n .getElementById(headingId)\n ?.scrollIntoView({ behavior: \"smooth\", block: \"start\" });\n};\n</script>\n\n<style lang=\"scss\" scoped>\n@use \"./index.scss\";\n</style>\n","<!--\n WordViewer — Word 文档预览子组件\n 负责: 目录导航 + 缩放 + 文档内容渲染\n-->\n<template>\n <div class=\"file-container word-container\">\n <div class=\"file-toolbar\">\n <div class=\"flex gap-2 items-center\">\n <NButton size=\"small\" @click=\"showOutline = !showOutline\">\n <template #icon>\n <C_Icon name=\"ic:outline-list\" />\n </template>\n {{ showOutline ? \"隐藏\" : \"显示\" }}目录\n </NButton>\n <NDivider vertical />\n <NButton\n size=\"small\"\n :disabled=\"wordZoom <= 50\"\n @click=\"adjustWordZoom('out')\"\n >\n <template #icon>\n <C_Icon name=\"ic:outline-zoom-out\" />\n </template>\n </NButton>\n <span class=\"text-sm text-gray-600 min-w-12 text-center\">\n {{ wordZoom }}%\n </span>\n <NButton\n size=\"small\"\n :disabled=\"wordZoom >= 200\"\n @click=\"adjustWordZoom('in')\"\n >\n <template #icon>\n <C_Icon name=\"ic:outline-zoom-in\" />\n </template>\n </NButton>\n <NButton size=\"small\" @click=\"adjustWordZoom('reset')\">\n <template #icon>\n <C_Icon name=\"ic:outline-fit-screen\" />\n </template>\n 重置\n </NButton>\n </div>\n </div>\n\n <div class=\"word-layout\">\n <div class=\"word-main\">\n <!-- 侧边栏目录 -->\n <div v-if=\"showOutline\" class=\"word-outline\">\n <div class=\"outline-header\">\n <h3 class=\"text-sm font-semibold\">文档目录</h3>\n </div>\n <div class=\"outline-content\">\n <div\n v-for=\"(heading, index) in headings\"\n :key=\"index\"\n class=\"outline-item\"\n :class=\"`level-${heading.level}`\"\n @click=\"scrollToHeading(heading.id)\"\n >\n {{ heading.text }}\n </div>\n </div>\n </div>\n\n <!-- 主要内容区域 -->\n <div class=\"word-content\">\n <div\n class=\"word-document\"\n :style=\"{\n transform: `scale(${wordZoom / 100})`,\n transformOrigin: 'top center',\n }\"\n v-html=\"content\"\n ></div>\n </div>\n </div>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref } from \"vue\";\nimport { NButton, NDivider } from \"naive-ui\";\nimport { createZoomHandler, ZOOM_CONFIGS } from \"../../data\";\nimport type { DocHeading } from \"../../types\";\n\ndefineProps<{\n content: string;\n headings: DocHeading[];\n}>();\n\nconst showOutline = ref(true);\nconst wordZoom = ref(100);\n\nconst adjustWordZoom = createZoomHandler(wordZoom, ZOOM_CONFIGS.word);\n\nconst scrollToHeading = (headingId: string) => {\n document\n .getElementById(headingId)\n ?.scrollIntoView({ behavior: \"smooth\", block: \"start\" });\n};\n</script>\n\n<style lang=\"scss\" scoped>\n@use \"./index.scss\";\n</style>\n","<!--\n ExcelViewer — Excel 表格预览子组件\n 负责: 工作表切换 + 表格渲染(合并单元格) + 分页 + 格式切换\n-->\n<template>\n <div class=\"file-container excel-container\">\n <!-- 工具栏 -->\n <div class=\"file-toolbar\">\n <div class=\"flex justify-between items-center\">\n <div class=\"flex gap-2 items-center\">\n <NTabs\n v-if=\"sheets.length > 1\"\n v-model:value=\"activeSheet\"\n type=\"card\"\n size=\"small\"\n >\n <NTabPane\n v-for=\"sheet in sheets\"\n :key=\"sheet.name\"\n :name=\"sheet.name\"\n :tab=\"sheet.name\"\n />\n </NTabs>\n <span v-else class=\"text-sm text-gray-600\">\n 工作表: {{ activeSheet }}\n </span>\n </div>\n\n <div class=\"flex gap-2 items-center\">\n <NButton size=\"small\" @click=\"showExcelFormat = !showExcelFormat\">\n <template #icon>\n <C_Icon name=\"ic:outline-format-paint\" />\n </template>\n {{ showExcelFormat ? \"紧凑视图\" : \"完整格式\" }}\n </NButton>\n </div>\n </div>\n </div>\n\n <div class=\"excel-viewer\">\n <!-- 信息面板 -->\n <div v-if=\"currentData.length > 0\" class=\"excel-info\">\n <NText depth=\"3\" class=\"text-sm\">\n 当前工作表: {{ activeSheet }} | 总行数: {{ currentData.length }} |\n 总列数: {{ currentColumns.length }} | 当前页:\n {{ currentExcelPage }}/{{ totalExcelPages }}\n </NText>\n </div>\n\n <!-- 表格 -->\n <div class=\"excel-table-container\">\n <div\n class=\"excel-table-wrapper\"\n :class=\"{ 'simple-mode': !showExcelFormat }\"\n >\n <table v-if=\"currentData.length > 0\" class=\"excel-table\">\n <thead>\n <tr>\n <th class=\"row-number\">行号</th>\n <th\n v-for=\"(col, index) in currentColumns\"\n :key=\"col.key\"\n class=\"excel-header\"\n :style=\"{ minWidth: col.width + 'px' }\"\n >\n <div class=\"header-content\">\n <span class=\"column-letter\">{{\n getColumnLetter(index)\n }}</span>\n <span class=\"column-title\">{{ col.title }}</span>\n </div>\n </th>\n </tr>\n </thead>\n <tbody>\n <tr\n v-for=\"(row, rowIndex) in paginatedData\"\n :key=\"rowIndex\"\n class=\"excel-row\"\n >\n <td class=\"row-number\">\n {{ (currentExcelPage - 1) * pageSize + rowIndex + 1 }}\n </td>\n <td\n v-for=\"col in currentColumns\"\n :key=\"col.key\"\n v-show=\"!row[col.key]?.hidden\"\n class=\"excel-cell\"\n :class=\"[\n getCellClass(row[col.key]?.value),\n row[col.key]?.merged ? 'merged-cell' : '',\n !showExcelFormat ? 'compact-cell' : '',\n ]\"\n :rowspan=\"row[col.key]?.rowspan || 1\"\n :colspan=\"row[col.key]?.colspan || 1\"\n :title=\"row[col.key]?.value\"\n >\n {{ formatCellValue(row[col.key]?.value) }}\n </td>\n </tr>\n </tbody>\n </table>\n\n <div v-else class=\"excel-empty\">\n <NEmpty description=\"该工作表没有数据或解析失败\">\n <template #extra>\n <NButton size=\"small\" @click=\"$emit('reload')\">\n 重新解析\n </NButton>\n </template>\n </NEmpty>\n </div>\n </div>\n\n <!-- 分页 -->\n <div v-if=\"totalExcelPages > 1\" class=\"excel-pagination\">\n <NPagination\n v-model:page=\"currentExcelPage\"\n :page-count=\"totalExcelPages\"\n :page-size=\"pageSize\"\n show-size-picker\n :page-sizes=\"PAGE_SIZE_OPTIONS\"\n @update:page-size=\"handlePageSizeChange\"\n />\n </div>\n </div>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, computed, watch } from \"vue\";\nimport { NButton, NTabs, NTabPane, NText, NEmpty, NPagination } from \"naive-ui\";\nimport {\n getColumnLetter,\n formatCellValue,\n getCellClass,\n PAGE_SIZE_OPTIONS,\n} from \"../../data\";\nimport type { ExcelSheet, ExcelRow, ExcelColumn } from \"../../types\";\n\nconst props = defineProps<{\n sheets: ExcelSheet[];\n}>();\n\ndefineEmits<{\n reload: [];\n}>();\n\n/* ==================== 内部状态 ==================== */\nconst activeSheet = ref(\"\");\nconst showExcelFormat = ref(false);\nconst currentExcelPage = ref(1);\nconst pageSize = ref(50);\n\n/* ==================== 当前工作表数据 ==================== */\nconst currentData = ref<ExcelRow[]>([]);\nconst currentColumns = ref<ExcelColumn[]>([]);\n\n/* ==================== 计算属性 ==================== */\nconst totalExcelPages = computed(() =>\n Math.ceil(currentData.value.length / pageSize.value),\n);\n\nconst paginatedData = computed(() => {\n const start = (currentExcelPage.value - 1) * pageSize.value;\n return currentData.value.slice(start, start + pageSize.value);\n});\n\n/* ==================== 方法 ==================== */\nconst handlePageSizeChange = (newPageSize: number) => {\n pageSize.value = newPageSize;\n currentExcelPage.value = 1;\n};\n\nconst syncSheetData = (sheetName: string) => {\n const sheet = props.sheets.find((s) => s.name === sheetName);\n if (sheet) {\n currentData.value = sheet.data;\n currentColumns.value = sheet.columns;\n currentExcelPage.value = 1;\n }\n};\n\n/* ==================== 监听器 ==================== */\nwatch(activeSheet, (newSheet) => {\n syncSheetData(newSheet);\n});\n\n/* sheets 变化时初始化 */\nwatch(\n () => props.sheets,\n (newSheets) => {\n if (newSheets.length > 0) {\n const [firstSheet] = newSheets;\n activeSheet.value = firstSheet.name;\n currentData.value = firstSheet.data;\n currentColumns.value = firstSheet.columns;\n currentExcelPage.value = 1;\n }\n },\n { immediate: true },\n);\n</script>\n\n<style lang=\"scss\" scoped>\n@use \"./index.scss\";\n</style>\n","<!--\n ExcelViewer — Excel 表格预览子组件\n 负责: 工作表切换 + 表格渲染(合并单元格) + 分页 + 格式切换\n-->\n<template>\n <div class=\"file-container excel-container\">\n <!-- 工具栏 -->\n <div class=\"file-toolbar\">\n <div class=\"flex justify-between items-center\">\n <div class=\"flex gap-2 items-center\">\n <NTabs\n v-if=\"sheets.length > 1\"\n v-model:value=\"activeSheet\"\n type=\"card\"\n size=\"small\"\n >\n <NTabPane\n v-for=\"sheet in sheets\"\n :key=\"sheet.name\"\n :name=\"sheet.name\"\n :tab=\"sheet.name\"\n />\n </NTabs>\n <span v-else class=\"text-sm text-gray-600\">\n 工作表: {{ activeSheet }}\n </span>\n </div>\n\n <div class=\"flex gap-2 items-center\">\n <NButton size=\"small\" @click=\"showExcelFormat = !showExcelFormat\">\n <template #icon>\n <C_Icon name=\"ic:outline-format-paint\" />\n </template>\n {{ showExcelFormat ? \"紧凑视图\" : \"完整格式\" }}\n </NButton>\n </div>\n </div>\n </div>\n\n <div class=\"excel-viewer\">\n <!-- 信息面板 -->\n <div v-if=\"currentData.length > 0\" class=\"excel-info\">\n <NText depth=\"3\" class=\"text-sm\">\n 当前工作表: {{ activeSheet }} | 总行数: {{ currentData.length }} |\n 总列数: {{ currentColumns.length }} | 当前页:\n {{ currentExcelPage }}/{{ totalExcelPages }}\n </NText>\n </div>\n\n <!-- 表格 -->\n <div class=\"excel-table-container\">\n <div\n class=\"excel-table-wrapper\"\n :class=\"{ 'simple-mode': !showExcelFormat }\"\n >\n <table v-if=\"currentData.length > 0\" class=\"excel-table\">\n <thead>\n <tr>\n <th class=\"row-number\">行号</th>\n <th\n v-for=\"(col, index) in currentColumns\"\n :key=\"col.key\"\n class=\"excel-header\"\n :style=\"{ minWidth: col.width + 'px' }\"\n >\n <div class=\"header-content\">\n <span class=\"column-letter\">{{\n getColumnLetter(index)\n }}</span>\n <span class=\"column-title\">{{ col.title }}</span>\n </div>\n </th>\n </tr>\n </thead>\n <tbody>\n <tr\n v-for=\"(row, rowIndex) in paginatedData\"\n :key=\"rowIndex\"\n class=\"excel-row\"\n >\n <td class=\"row-number\">\n {{ (currentExcelPage - 1) * pageSize + rowIndex + 1 }}\n </td>\n <td\n v-for=\"col in currentColumns\"\n :key=\"col.key\"\n v-show=\"!row[col.key]?.hidden\"\n class=\"excel-cell\"\n :class=\"[\n getCellClass(row[col.key]?.value),\n row[col.key]?.merged ? 'merged-cell' : '',\n !showExcelFormat ? 'compact-cell' : '',\n ]\"\n :rowspan=\"row[col.key]?.rowspan || 1\"\n :colspan=\"row[col.key]?.colspan || 1\"\n :title=\"row[col.key]?.value\"\n >\n {{ formatCellValue(row[col.key]?.value) }}\n </td>\n </tr>\n </tbody>\n </table>\n\n <div v-else class=\"excel-empty\">\n <NEmpty description=\"该工作表没有数据或解析失败\">\n <template #extra>\n <NButton size=\"small\" @click=\"$emit('reload')\">\n 重新解析\n </NButton>\n </template>\n </NEmpty>\n </div>\n </div>\n\n <!-- 分页 -->\n <div v-if=\"totalExcelPages > 1\" class=\"excel-pagination\">\n <NPagination\n v-model:page=\"currentExcelPage\"\n :page-count=\"totalExcelPages\"\n :page-size=\"pageSize\"\n show-size-picker\n :page-sizes=\"PAGE_SIZE_OPTIONS\"\n @update:page-size=\"handlePageSizeChange\"\n />\n </div>\n </div>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, computed, watch } from \"vue\";\nimport { NButton, NTabs, NTabPane, NText, NEmpty, NPagination } from \"naive-ui\";\nimport {\n getColumnLetter,\n formatCellValue,\n getCellClass,\n PAGE_SIZE_OPTIONS,\n} from \"../../data\";\nimport type { ExcelSheet, ExcelRow, ExcelColumn } from \"../../types\";\n\nconst props = defineProps<{\n sheets: ExcelSheet[];\n}>();\n\ndefineEmits<{\n reload: [];\n}>();\n\n/* ==================== 内部状态 ==================== */\nconst activeSheet = ref(\"\");\nconst showExcelFormat = ref(false);\nconst currentExcelPage = ref(1);\nconst pageSize = ref(50);\n\n/* ==================== 当前工作表数据 ==================== */\nconst currentData = ref<ExcelRow[]>([]);\nconst currentColumns = ref<ExcelColumn[]>([]);\n\n/* ==================== 计算属性 ==================== */\nconst totalExcelPages = computed(() =>\n Math.ceil(currentData.value.length / pageSize.value),\n);\n\nconst paginatedData = computed(() => {\n const start = (currentExcelPage.value - 1) * pageSize.value;\n return currentData.value.slice(start, start + pageSize.value);\n});\n\n/* ==================== 方法 ==================== */\nconst handlePageSizeChange = (newPageSize: number) => {\n pageSize.value = newPageSize;\n currentExcelPage.value = 1;\n};\n\nconst syncSheetData = (sheetName: string) => {\n const sheet = props.sheets.find((s) => s.name === sheetName);\n if (sheet) {\n currentData.value = sheet.data;\n currentColumns.value = sheet.columns;\n currentExcelPage.value = 1;\n }\n};\n\n/* ==================== 监听器 ==================== */\nwatch(activeSheet, (newSheet) => {\n syncSheetData(newSheet);\n});\n\n/* sheets 变化时初始化 */\nwatch(\n () => props.sheets,\n (newSheets) => {\n if (newSheets.length > 0) {\n const [firstSheet] = newSheets;\n activeSheet.value = firstSheet.name;\n currentData.value = firstSheet.data;\n currentColumns.value = firstSheet.columns;\n currentExcelPage.value = 1;\n }\n },\n { immediate: true },\n);\n</script>\n\n<style lang=\"scss\" scoped>\n@use \"./index.scss\";\n</style>\n","/**\r\n * useFilePreview — 文件预览核心 composable\r\n * 管理:文件状态、加载、类型检测、下载\r\n */\r\nimport { ref, computed, watch, onUnmounted, type Ref } from \"vue\";\r\nimport {\r\n extractFileNameFromUrl,\r\n getFileType,\r\n getFileConfig,\r\n loadPdf,\r\n loadWord,\r\n loadExcel,\r\n} from \"../data\";\r\nimport type { FilePreviewType, DocHeading, ExcelSheet } from \"../types\";\r\n\r\nexport interface UseFilePreviewOptions {\r\n file: Ref<File | undefined>;\r\n url: Ref<string | undefined>;\r\n fileName: Ref<string>;\r\n}\r\n\r\n/**\r\n * 文件预览核心 composable — 管理文件状态、加载、类型检测、下载\r\n * @param options - 文件源配置(file / url / fileName)\r\n * @param emit - 组件事件发射器\r\n */\r\nexport function useFilePreview(\r\n options: UseFilePreviewOptions,\r\n emit: {\r\n (e: \"preview\", file: File | string): void;\r\n (e: \"download\", file: File | string): void;\r\n },\r\n) {\r\n const { file, url, fileName } = options;\r\n\r\n /* ==================== 基础状态 ==================== */\r\n const loading = ref(false);\r\n const error = ref(\"\");\r\n const fileSize = ref(0);\r\n const showModal = ref(false);\r\n\r\n /* ==================== 解析后的数据 ==================== */\r\n const pdfUrl = ref(\"\");\r\n const pdfTotalPages = ref(0);\r\n\r\n const wordContent = ref(\"\");\r\n const wordHeadings = ref<DocHeading[]>([]);\r\n\r\n const excelSheets = ref<ExcelSheet[]>([]);\r\n\r\n /* ==================== 计算属性 ==================== */\r\n const displayFileName = computed(() => {\r\n if (fileName.value && fileName.value !== \"未知文件\") return fileName.value;\r\n if (file.value?.name) return file.value.name;\r\n if (url.value) return extractFileNameFromUrl(url.value);\r\n return \"未知文件\";\r\n });\r\n\r\n const fileType = computed<FilePreviewType>(() =>\r\n getFileType(displayFileName.value),\r\n );\r\n const fileConfig = computed(() => getFileConfig(fileType.value));\r\n\r\n /* ==================== 内部方法 ==================== */\r\n const clearState = () => {\r\n error.value = \"\";\r\n loading.value = false;\r\n pdfUrl.value = \"\";\r\n pdfTotalPages.value = 0;\r\n wordContent.value = \"\";\r\n wordHeadings.value = [];\r\n excelSheets.value = [];\r\n };\r\n\r\n const setError = (msg: string) => {\r\n error.value = msg;\r\n loading.value = false;\r\n };\r\n\r\n /* ==================== 文件解析 ==================== */\r\n const resolveFile = async (): Promise<File> => {\r\n if (file.value) {\r\n fileSize.value = file.value.size;\r\n return file.value;\r\n }\r\n if (url.value) {\r\n const response = await fetch(url.value);\r\n if (!response.ok)\r\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\r\n\r\n const blob = await response.blob();\r\n const resolved = new File([blob], displayFileName.value, {\r\n type: blob.type,\r\n });\r\n fileSize.value = resolved.size;\r\n return resolved;\r\n }\r\n throw new Error(\"未提供文件或URL\");\r\n };\r\n\r\n const loadByType = async (\r\n currentFile: File,\r\n type: FilePreviewType,\r\n ): Promise<void> => {\r\n switch (type) {\r\n case \"pdf\": {\r\n const result = await loadPdf(currentFile);\r\n pdfUrl.value = result.url;\r\n pdfTotalPages.value = result.totalPages;\r\n break;\r\n }\r\n case \"word\": {\r\n const result = await loadWord(currentFile);\r\n wordContent.value = result.content;\r\n wordHeadings.value = result.headings;\r\n break;\r\n }\r\n case \"excel\": {\r\n const result = await loadExcel(currentFile);\r\n excelSheets.value = result.sheets;\r\n break;\r\n }\r\n default:\r\n throw new Error(\"不支持的文件格式\");\r\n }\r\n };\r\n\r\n /* ==================== 核心方法 ==================== */\r\n const loadFile = async () => {\r\n if (!file.value && !url.value) {\r\n setError(\"未提供文件或URL\");\r\n return;\r\n }\r\n\r\n clearState();\r\n loading.value = true;\r\n\r\n try {\r\n const currentFile = await resolveFile();\r\n await loadByType(currentFile, fileType.value);\r\n loading.value = false;\r\n } catch (err) {\r\n const errorMessage = err instanceof Error ? err.message : \"未知错误\";\r\n setError(`${fileType.value.toUpperCase()}文件加载失败: ${errorMessage}`);\r\n }\r\n };\r\n\r\n const openPreview = async () => {\r\n showModal.value = true;\r\n await loadFile();\r\n emit(\"preview\", file.value || url.value!);\r\n };\r\n\r\n const downloadFile = () => {\r\n if (file.value) {\r\n const downloadUrl = URL.createObjectURL(file.value);\r\n const a = Object.assign(document.createElement(\"a\"), {\r\n href: downloadUrl,\r\n download: displayFileName.value,\r\n });\r\n a.click();\r\n URL.revokeObjectURL(downloadUrl);\r\n } else if (url.value) {\r\n window.open(url.value, \"_blank\");\r\n }\r\n emit(\"download\", file.value || url.value!);\r\n };\r\n\r\n /* ==================== 副作用 ==================== */\r\n watch(\r\n () => file.value?.size,\r\n (newSize) => {\r\n fileSize.value = newSize || 0;\r\n },\r\n { immediate: true },\r\n );\r\n\r\n onUnmounted(() => {\r\n if (pdfUrl.value?.startsWith(\"blob:\")) {\r\n URL.revokeObjectURL(pdfUrl.value.split(\"#\")[0]);\r\n }\r\n });\r\n\r\n return {\r\n /* 状态 */\r\n loading,\r\n error,\r\n fileSize,\r\n showModal,\r\n /* 解析数据 */\r\n pdfUrl,\r\n pdfTotalPages,\r\n wordContent,\r\n wordHeadings,\r\n excelSheets,\r\n /* 计算属性 */\r\n displayFileName,\r\n fileType,\r\n fileConfig,\r\n /* 方法 */\r\n loadFile,\r\n openPreview,\r\n downloadFile,\r\n };\r\n}\r\n","/**\r\n * useFullscreen — 全屏切换 composable\r\n */\r\nimport { ref, onMounted, onUnmounted, type Ref } from \"vue\";\r\nimport { FULLSCREEN_EVENTS } from \"../data\";\r\n\r\n/**\r\n * 全屏切换 composable — 管理全屏状态与跨浏览器兼容\r\n * @param containerRef - 需要全屏的容器元素引用\r\n */\r\nexport function useFullscreen(containerRef: Ref<HTMLElement | undefined>) {\r\n const isFullscreen = ref(false);\r\n\r\n const handleFullscreenChange = () => {\r\n isFullscreen.value = !!document.fullscreenElement;\r\n };\r\n\r\n const tryMethods = (\r\n methods: Array<() => Promise<void>>,\r\n index = 0,\r\n ): Promise<void> => {\r\n if (index >= methods.length) {\r\n console.warn(\"无法切换全屏状态\");\r\n return Promise.resolve();\r\n }\r\n return methods[index]().catch(() => tryMethods(methods, index + 1));\r\n };\r\n\r\n const toggleFullscreen = async () => {\r\n const element = containerRef.value;\r\n if (!element) return;\r\n\r\n const isCurrentlyFullscreen = !!document.fullscreenElement;\r\n\r\n const methods = isCurrentlyFullscreen\r\n ? [\r\n () => document.exitFullscreen(),\r\n () => (document as any).webkitExitFullscreen(),\r\n () => (document as any).mozCancelFullScreen(),\r\n () => (document as any).msExitFullscreen(),\r\n ]\r\n : [\r\n () => element.requestFullscreen(),\r\n () => (element as any).webkitRequestFullscreen(),\r\n () => (element as any).mozRequestFullScreen(),\r\n () => (element as any).msRequestFullscreen(),\r\n ];\r\n\r\n await tryMethods(methods);\r\n };\r\n\r\n const exitFullscreen = async () => {\r\n if (document.fullscreenElement) {\r\n try {\r\n await document.exitFullscreen();\r\n } catch {\r\n /* ignore */\r\n }\r\n }\r\n isFullscreen.value = false;\r\n };\r\n\r\n onMounted(() => {\r\n FULLSCREEN_EVENTS.forEach((event) =>\r\n document.addEventListener(event, handleFullscreenChange),\r\n );\r\n });\r\n\r\n onUnmounted(() => {\r\n FULLSCREEN_EVENTS.forEach((event) =>\r\n document.removeEventListener(event, handleFullscreenChange),\r\n );\r\n });\r\n\r\n return { isFullscreen, toggleFullscreen, exitFullscreen };\r\n}\r\n","<!--\n * @Author: ChenYu ycyplus@gmail.com\n * @Date: 2025-07-01\n * @Description: 文件预览组件(PDF/Word/Excel)\n * @Migration: naive-ui-components 组件库迁移版本\n * Copyright (c) 2025 by CHENY, All Rights Reserved.\n-->\n\n<template>\n <div class=\"c-file-preview-wrapper\">\n <!-- 文件信息卡片模式 -->\n <div\n v-if=\"!autoPreview\"\n class=\"file-info-card\"\n >\n <div class=\"file-info\">\n <div class=\"file-icon\">\n <C_Icon\n :name=\"fileConfig.icon\"\n :size=\"40\"\n :color=\"fileConfig.color\"\n />\n </div>\n\n <div class=\"file-details\">\n <div class=\"file-name\">\n <NEllipsis style=\"max-width: 250px\">{{\n displayFileName\n }}</NEllipsis>\n <NTag\n :type=\"fileConfig.tagType as any\"\n size=\"small\"\n >\n {{ fileType.toUpperCase() }}\n </NTag>\n </div>\n\n <div class=\"file-meta\">\n <span class=\"file-size\">{{ formatFileSize(fileSize) }}</span>\n </div>\n </div>\n\n <div class=\"file-actions\">\n <NButton\n type=\"primary\"\n @click=\"openPreview\"\n >\n <template #icon>\n <C_Icon name=\"ic:outline-visibility\" />\n </template>\n 预览\n </NButton>\n\n <NButton\n type=\"tertiary\"\n @click=\"downloadFile\"\n >\n <template #icon>\n <C_Icon name=\"ic:outline-download\" />\n </template>\n 下载\n </NButton>\n </div>\n </div>\n </div>\n\n <!-- 模态框预览 -->\n <NModal\n v-model:show=\"showModal\"\n :mask-closable=\"false\"\n :closable=\"false\"\n :auto-focus=\"false\"\n transform-origin=\"center\"\n style=\"\n width: 85vw;\n max-width: 1200px;\n min-width: 800px;\n height: 75vh;\n max-height: 700px;\n min-height: 500px;\n \"\n >\n <div\n ref=\"modalContainer\"\n class=\"modal-container\"\n >\n <!-- 自定义头部 -->\n <div class=\"modal-header\">\n <div class=\"modal-title\">\n <C_Icon\n :name=\"fileConfig.icon\"\n :size=\"20\"\n :color=\"fileConfig.color\"\n />\n <span>{{ displayFileName }}</span>\n </div>\n <div class=\"modal-actions\">\n <NButton\n size=\"small\"\n type=\"tertiary\"\n @click=\"downloadFile\"\n >\n <template #icon>\n <C_Icon name=\"ic:outline-download\" />\n </template>\n 下载\n </NButton>\n <NButton\n size=\"small\"\n type=\"tertiary\"\n @click=\"showModal = false\"\n >\n <template #icon>\n <C_Icon name=\"ic:outline-close\" />\n </template>\n </NButton>\n </div>\n </div>\n\n <!-- 预览内容 -->\n <div class=\"modal-content\">\n <!-- 文件信息头部 -->\n <div class=\"preview-header\">\n <div class=\"flex justify-between items-center\">\n <div class=\"flex items-center gap-3\">\n <NTag\n :type=\"fileConfig.tagType as any\"\n size=\"small\"\n >\n <template #icon>\n <C_Icon :name=\"fileConfig.icon\" />\n </template>\n {{ fileType.toUpperCase() }}\n </NTag>\n <NEllipsis style=\"max-width: 300px\">{{\n displayFileName\n }}</NEllipsis>\n <span class=\"text-sm text-gray-500\">{{\n formatFileSize(fileSize)\n }}</span>\n </div>\n\n <div class=\"flex gap-2\">\n <NButton\n size=\"small\"\n type=\"tertiary\"\n :disabled=\"loading\"\n @click=\"loadFile\"\n >\n <template #icon>\n <C_Icon name=\"ic:outline-refresh\" />\n </template>\n 刷新\n </NButton>\n <NButton\n size=\"small\"\n type=\"primary\"\n @click=\"toggleFullscreen\"\n >\n <template #icon>\n <C_Icon\n :name=\"\n isFullscreen\n ? 'ic:outline-fullscreen-exit'\n : 'ic:outline-fullscreen'\n \"\n />\n </template>\n {{ isFullscreen ? '退出全屏' : '全屏' }}\n </NButton>\n </div>\n </div>\n </div>\n\n <!-- 预览内容区域 -->\n <div class=\"preview-content\">\n <!-- 加载和错误状态 -->\n <template v-if=\"loading || error\">\n <div class=\"status-container\">\n <NSpin\n v-if=\"loading\"\n size=\"large\"\n >\n <template #description>\n 正在加载{{ fileType.toUpperCase() }}文件...\n </template>\n </NSpin>\n <NResult\n v-else\n status=\"error\"\n title=\"预览失败\"\n :description=\"error\"\n >\n <template #footer>\n <NButton @click=\"loadFile\">重试</NButton>\n </template>\n </NResult>\n </div>\n </template>\n\n <!-- 文件预览 — 委托给子组件 -->\n <template v-else>\n <PdfViewer\n v-if=\"fileType === 'pdf'\"\n :pdf-url=\"pdfUrl\"\n :total-pages=\"pdfTotalPages\"\n />\n\n <WordViewer\n v-else-if=\"fileType === 'word'\"\n :content=\"wordContent\"\n :headings=\"wordHeadings\"\n />\n\n <ExcelViewer\n v-else-if=\"fileType === 'excel'\"\n :sheets=\"excelSheets\"\n @reload=\"loadFile\"\n />\n\n <!-- 不支持的文件类型 -->\n <NResult\n v-else\n status=\"warning\"\n title=\"不支持的文件格式\"\n :description=\"`暂不支持预览 ${fileType.toUpperCase()} 格式文件`\"\n />\n </template>\n </div>\n </div>\n </div>\n </NModal>\n </div>\n</template>\n\n<script setup lang=\"ts\">\n import { ref, toRefs, watch } from 'vue'\n import { NButton, NEllipsis, NTag, NModal, NSpin, NResult } from 'naive-ui'\n import { formatFileSize } from './data'\n import PdfViewer from './components/PdfViewer/index.vue'\n import WordViewer from './components/WordViewer/index.vue'\n import ExcelViewer from './components/ExcelViewer/index.vue'\n import { useFilePreview } from './composables/useFilePreview'\n import { useFullscreen } from './composables/useFullscreen'\n\n defineOptions({ name: 'C_FilePreview' })\n\n const props = withDefaults(\n defineProps<{\n file?: File\n url?: string\n fileName?: string\n autoPreview?: boolean\n }>(),\n {\n fileName: '未知文件',\n autoPreview: false,\n }\n )\n\n const { file, url, fileName: propFileName, autoPreview } = toRefs(props)\n\n const emit = defineEmits<{\n preview: [file: File | string]\n download: [file: File | string]\n }>()\n\n /* ==================== Composables ==================== */\n const {\n loading,\n error,\n fileSize,\n showModal,\n pdfUrl,\n pdfTotalPages,\n wordContent,\n wordHeadings,\n excelSheets,\n displayFileName,\n fileType,\n fileConfig,\n loadFile,\n openPreview,\n downloadFile,\n } = useFilePreview({ file, url, fileName: propFileName }, emit)\n\n const modalContainer = ref<HTMLElement>()\n const { isFullscreen, toggleFullscreen, exitFullscreen } =\n useFullscreen(modalContainer)\n\n /* ==================== Modal 关闭时退出全屏 ==================== */\n watch(showModal, isShow => {\n if (!isShow) exitFullscreen()\n })\n</script>\n\n<style lang=\"scss\" scoped>\n @use './index.scss';\n</style>\n","<!--\n * @Author: ChenYu ycyplus@gmail.com\n * @Date: 2025-07-01\n * @Description: 文件预览组件(PDF/Word/Excel)\n * @Migration: naive-ui-components 组件库迁移版本\n * Copyright (c) 2025 by CHENY, All Rights Reserved.\n-->\n\n<template>\n <div class=\"c-file-preview-wrapper\">\n <!-- 文件信息卡片模式 -->\n <div\n v-if=\"!autoPreview\"\n class=\"file-info-card\"\n >\n <div class=\"file-info\">\n <div class=\"file-icon\">\n <C_Icon\n :name=\"fileConfig.icon\"\n :size=\"40\"\n :color=\"fileConfig.color\"\n />\n </div>\n\n <div class=\"file-details\">\n <div class=\"file-name\">\n <NEllipsis style=\"max-width: 250px\">{{\n displayFileName\n }}</NEllipsis>\n <NTag\n :type=\"fileConfig.tagType as any\"\n size=\"small\"\n >\n {{ fileType.toUpperCase() }}\n </NTag>\n </div>\n\n <div class=\"file-meta\">\n <span class=\"file-size\">{{ formatFileSize(fileSize) }}</span>\n </div>\n </div>\n\n <div class=\"file-actions\">\n <NButton\n type=\"primary\"\n @click=\"openPreview\"\n >\n <template #icon>\n <C_Icon name=\"ic:outline-visibility\" />\n </template>\n 预览\n </NButton>\n\n <NButton\n type=\"tertiary\"\n @click=\"downloadFile\"\n >\n <template #icon>\n <C_Icon name=\"ic:outline-download\" />\n </template>\n 下载\n </NButton>\n </div>\n </div>\n </div>\n\n <!-- 模态框预览 -->\n <NModal\n v-model:show=\"showModal\"\n :mask-closable=\"false\"\n :closable=\"false\"\n :auto-focus=\"false\"\n transform-origin=\"center\"\n style=\"\n width: 85vw;\n max-width: 1200px;\n min-width: 800px;\n height: 75vh;\n max-height: 700px;\n min-height: 500px;\n \"\n >\n <div\n ref=\"modalContainer\"\n class=\"modal-container\"\n >\n <!-- 自定义头部 -->\n <div class=\"modal-header\">\n <div class=\"modal-title\">\n <C_Icon\n :name=\"fileConfig.icon\"\n :size=\"20\"\n :color=\"fileConfig.color\"\n />\n <span>{{ displayFileName }}</span>\n </div>\n <div class=\"modal-actions\">\n <NButton\n size=\"small\"\n type=\"tertiary\"\n @click=\"downloadFile\"\n >\n <template #icon>\n <C_Icon name=\"ic:outline-download\" />\n </template>\n 下载\n </NButton>\n <NButton\n size=\"small\"\n type=\"tertiary\"\n @click=\"showModal = false\"\n >\n <template #icon>\n <C_Icon name=\"ic:outline-close\" />\n </template>\n </NButton>\n </div>\n </div>\n\n <!-- 预览内容 -->\n <div class=\"modal-content\">\n <!-- 文件信息头部 -->\n <div class=\"preview-header\">\n <div class=\"flex justify-between items-center\">\n <div class=\"flex items-center gap-3\">\n <NTag\n :type=\"fileConfig.tagType as any\"\n size=\"small\"\n >\n <template #icon>\n <C_Icon :name=\"fileConfig.icon\" />\n </template>\n {{ fileType.toUpperCase() }}\n </NTag>\n <NEllipsis style=\"max-width: 300px\">{{\n displayFileName\n }}</NEllipsis>\n <span class=\"text-sm text-gray-500\">{{\n formatFileSize(fileSize)\n }}</span>\n </div>\n\n <div class=\"flex gap-2\">\n <NButton\n size=\"small\"\n type=\"tertiary\"\n :disabled=\"loading\"\n @click=\"loadFile\"\n >\n <template #icon>\n <C_Icon name=\"ic:outline-refresh\" />\n </template>\n 刷新\n </NButton>\n <NButton\n size=\"small\"\n type=\"primary\"\n @click=\"toggleFullscreen\"\n >\n <template #icon>\n <C_Icon\n :name=\"\n isFullscreen\n ? 'ic:outline-fullscreen-exit'\n : 'ic:outline-fullscreen'\n \"\n />\n </template>\n {{ isFullscreen ? '退出全屏' : '全屏' }}\n </NButton>\n </div>\n </div>\n </div>\n\n <!-- 预览内容区域 -->\n <div class=\"preview-content\">\n <!-- 加载和错误状态 -->\n <template v-if=\"loading || error\">\n <div class=\"status-container\">\n <NSpin\n v-if=\"loading\"\n size=\"large\"\n >\n <template #description>\n 正在加载{{ fileType.toUpperCase() }}文件...\n </template>\n </NSpin>\n <NResult\n v-else\n status=\"error\"\n title=\"预览失败\"\n :description=\"error\"\n >\n <template #footer>\n <NButton @click=\"loadFile\">重试</NButton>\n </template>\n </NResult>\n </div>\n </template>\n\n <!-- 文件预览 — 委托给子组件 -->\n <template v-else>\n <PdfViewer\n v-if=\"fileType === 'pdf'\"\n :pdf-url=\"pdfUrl\"\n :total-pages=\"pdfTotalPages\"\n />\n\n <WordViewer\n v-else-if=\"fileType === 'word'\"\n :content=\"wordContent\"\n :headings=\"wordHeadings\"\n />\n\n <ExcelViewer\n v-else-if=\"fileType === 'excel'\"\n :sheets=\"excelSheets\"\n @reload=\"loadFile\"\n />\n\n <!-- 不支持的文件类型 -->\n <NResult\n v-else\n status=\"warning\"\n title=\"不支持的文件格式\"\n :description=\"`暂不支持预览 ${fileType.toUpperCase()} 格式文件`\"\n />\n </template>\n </div>\n </div>\n </div>\n </NModal>\n </div>\n</template>\n\n<script setup lang=\"ts\">\n import { ref, toRefs, watch } from 'vue'\n import { NButton, NEllipsis, NTag, NModal, NSpin, NResult } from 'naive-ui'\n import { formatFileSize } from './data'\n import PdfViewer from './components/PdfViewer/index.vue'\n import WordViewer from './components/WordViewer/index.vue'\n import ExcelViewer from './components/ExcelViewer/index.vue'\n import { useFilePreview } from './composables/useFilePreview'\n import { useFullscreen } from './composables/useFullscreen'\n\n defineOptions({ name: 'C_FilePreview' })\n\n const props = withDefaults(\n defineProps<{\n file?: File\n url?: string\n fileName?: string\n autoPreview?: boolean\n }>(),\n {\n fileName: '未知文件',\n autoPreview: false,\n }\n )\n\n const { file, url, fileName: propFileName, autoPreview } = toRefs(props)\n\n const emit = defineEmits<{\n preview: [file: File | string]\n download: [file: File | string]\n }>()\n\n /* ==================== Composables ==================== */\n const {\n loading,\n error,\n fileSize,\n showModal,\n pdfUrl,\n pdfTotalPages,\n wordContent,\n wordHeadings,\n excelSheets,\n displayFileName,\n fileType,\n fileConfig,\n loadFile,\n openPreview,\n downloadFile,\n } = useFilePreview({ file, url, fileName: propFileName }, emit)\n\n const modalContainer = ref<HTMLElement>()\n const { isFullscreen, toggleFullscreen, exitFullscreen } =\n useFullscreen(modalContainer)\n\n /* ==================== Modal 关闭时退出全屏 ==================== */\n watch(showModal, isShow => {\n if (!isShow) exitFullscreen()\n })\n</script>\n\n<style lang=\"scss\" scoped>\n @use './index.scss';\n</style>\n"],"mappings":"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"}
|