@robot-admin/naive-ui-components 0.3.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/README.md +257 -0
- package/dist/C_ActionBar-DWN-woTc.css.map +1 -0
- package/dist/C_ActionBar.cjs +5 -0
- package/dist/C_ActionBar.d.cts +2 -0
- package/dist/C_ActionBar.d.ts +2 -0
- package/dist/C_ActionBar.js +4 -0
- package/dist/C_ActionBar2.js +196 -0
- package/dist/C_ActionBar2.js.map +1 -0
- package/dist/C_AntV-AFKyK6hH.css.map +1 -0
- package/dist/C_AntV.cjs +8 -0
- package/dist/C_AntV.d.cts +2 -0
- package/dist/C_AntV.d.ts +2 -0
- package/dist/C_AntV.js +4 -0
- package/dist/C_AntV2.js +3150 -0
- package/dist/C_AntV2.js.map +1 -0
- package/dist/C_Barcode-P_EFj8dC.css.map +1 -0
- package/dist/C_Barcode.cjs +4 -0
- package/dist/C_Barcode.d.cts +2 -0
- package/dist/C_Barcode.d.ts +2 -0
- package/dist/C_Barcode.js +3 -0
- package/dist/C_Barcode2.js +68 -0
- package/dist/C_Barcode2.js.map +1 -0
- package/dist/C_Captcha-C-ef41xw.css.map +1 -0
- package/dist/C_Captcha.cjs +4 -0
- package/dist/C_Captcha.d.cts +2 -0
- package/dist/C_Captcha.d.ts +2 -0
- package/dist/C_Captcha.js +3 -0
- package/dist/C_Captcha2.js +155 -0
- package/dist/C_Captcha2.js.map +1 -0
- package/dist/C_Cascade-D9kNsjsV.css.map +1 -0
- package/dist/C_Cascade.cjs +4 -0
- package/dist/C_Cascade.d.cts +2 -0
- package/dist/C_Cascade.d.ts +2 -0
- package/dist/C_Cascade.js +3 -0
- package/dist/C_Cascade2.js +103 -0
- package/dist/C_Cascade2.js.map +1 -0
- package/dist/C_City-BCQ4ipiK.css.map +1 -0
- package/dist/C_City.cjs +4 -0
- package/dist/C_City.d.cts +2 -0
- package/dist/C_City.d.ts +2 -0
- package/dist/C_City.js +3 -0
- package/dist/C_City2.js +841 -0
- package/dist/C_City2.js.map +1 -0
- package/dist/C_Code-C9kvvEmO.css.map +1 -0
- package/dist/C_Code.cjs +5 -0
- package/dist/C_Code.d.cts +2 -0
- package/dist/C_Code.d.ts +2 -0
- package/dist/C_Code.js +4 -0
- package/dist/C_Code2.js +346 -0
- package/dist/C_Code2.js.map +1 -0
- package/dist/C_CollapsePanel-BUJHuYcU.css.map +1 -0
- package/dist/C_CollapsePanel.cjs +6 -0
- package/dist/C_CollapsePanel.d.cts +2 -0
- package/dist/C_CollapsePanel.d.ts +2 -0
- package/dist/C_CollapsePanel.js +4 -0
- package/dist/C_CollapsePanel2.js +319 -0
- package/dist/C_CollapsePanel2.js.map +1 -0
- package/dist/C_Cron-yx2Ob4Jl.css.map +1 -0
- package/dist/C_Cron.cjs +15 -0
- package/dist/C_Cron.d.cts +2 -0
- package/dist/C_Cron.d.ts +2 -0
- package/dist/C_Cron.js +4 -0
- package/dist/C_Cron2.js +1209 -0
- package/dist/C_Cron2.js.map +1 -0
- package/dist/C_Date.cjs +4 -0
- package/dist/C_Date.d.cts +2 -0
- package/dist/C_Date.d.ts +2 -0
- package/dist/C_Date.js +3 -0
- package/dist/C_Date2.js +219 -0
- package/dist/C_Date2.js.map +1 -0
- package/dist/C_Draggable-C483syRC.css.map +1 -0
- package/dist/C_Draggable.cjs +5 -0
- package/dist/C_Draggable.d.cts +2 -0
- package/dist/C_Draggable.d.ts +2 -0
- package/dist/C_Draggable.js +3 -0
- package/dist/C_Draggable2.js +295 -0
- package/dist/C_Draggable2.js.map +1 -0
- package/dist/C_Editor-Bp0SyIEw.css.map +1 -0
- package/dist/C_Editor.cjs +4 -0
- package/dist/C_Editor.d.cts +2 -0
- package/dist/C_Editor.d.ts +2 -0
- package/dist/C_Editor.js +3 -0
- package/dist/C_Editor2.js +160 -0
- package/dist/C_Editor2.js.map +1 -0
- package/dist/C_FilePreview-CPqvhoCy.css.map +1 -0
- package/dist/C_FilePreview.cjs +6 -0
- package/dist/C_FilePreview.d.cts +2 -0
- package/dist/C_FilePreview.d.ts +2 -0
- package/dist/C_FilePreview.js +3 -0
- package/dist/C_FilePreview2.js +1031 -0
- package/dist/C_FilePreview2.js.map +1 -0
- package/dist/C_Form-Jx7PY3sT.css.map +1 -0
- package/dist/C_Form.cjs +15 -0
- package/dist/C_Form.d.cts +2 -0
- package/dist/C_Form.d.ts +2 -0
- package/dist/C_Form.js +4 -0
- package/dist/C_Form2.js +2510 -0
- package/dist/C_Form2.js.map +1 -0
- package/dist/C_FormSearch-DvRgxlRn.css.map +1 -0
- package/dist/C_FormSearch.cjs +6 -0
- package/dist/C_FormSearch.d.cts +2 -0
- package/dist/C_FormSearch.d.ts +2 -0
- package/dist/C_FormSearch.js +3 -0
- package/dist/C_FormSearch2.js +356 -0
- package/dist/C_FormSearch2.js.map +1 -0
- package/dist/C_FormulaEditor-DtGkt4T_.css.map +1 -0
- package/dist/C_FormulaEditor.cjs +13 -0
- package/dist/C_FormulaEditor.d.cts +2 -0
- package/dist/C_FormulaEditor.d.ts +2 -0
- package/dist/C_FormulaEditor.js +4 -0
- package/dist/C_FormulaEditor2.js +1433 -0
- package/dist/C_FormulaEditor2.js.map +1 -0
- package/dist/C_FullCalendar-BF7H0YIx.css.map +1 -0
- package/dist/C_FullCalendar.cjs +9 -0
- package/dist/C_FullCalendar.d.cts +2 -0
- package/dist/C_FullCalendar.d.ts +2 -0
- package/dist/C_FullCalendar.js +3 -0
- package/dist/C_FullCalendar2.js +377 -0
- package/dist/C_FullCalendar2.js.map +1 -0
- package/dist/C_Guide.cjs +4 -0
- package/dist/C_Guide.d.cts +2 -0
- package/dist/C_Guide.d.ts +2 -0
- package/dist/C_Guide.js +3 -0
- package/dist/C_Guide2.js +58 -0
- package/dist/C_Guide2.js.map +1 -0
- package/dist/C_Icon.cjs +4 -0
- package/dist/C_Icon.d.cts +2 -0
- package/dist/C_Icon.d.ts +2 -0
- package/dist/C_Icon.js +3 -0
- package/dist/C_Icon2.js +286 -0
- package/dist/C_Icon2.js.map +1 -0
- package/dist/C_ImageCropper-BVJfUufl.css.map +1 -0
- package/dist/C_ImageCropper.cjs +6 -0
- package/dist/C_ImageCropper.d.cts +2 -0
- package/dist/C_ImageCropper.d.ts +2 -0
- package/dist/C_ImageCropper.js +4 -0
- package/dist/C_ImageCropper2.js +723 -0
- package/dist/C_ImageCropper2.js.map +1 -0
- package/dist/C_Language.cjs +4 -0
- package/dist/C_Language.d.cts +2 -0
- package/dist/C_Language.d.ts +2 -0
- package/dist/C_Language.js +3 -0
- package/dist/C_Language2.js +72 -0
- package/dist/C_Language2.js.map +1 -0
- package/dist/C_Map-DpzeuWdX.css.map +1 -0
- package/dist/C_Map.cjs +7 -0
- package/dist/C_Map.d.cts +2 -0
- package/dist/C_Map.d.ts +2 -0
- package/dist/C_Map.js +3 -0
- package/dist/C_Map2.js +199 -0
- package/dist/C_Map2.js.map +1 -0
- package/dist/C_Markdown-BEjxknqd.css.map +1 -0
- package/dist/C_Markdown.cjs +4 -0
- package/dist/C_Markdown.d.cts +2 -0
- package/dist/C_Markdown.d.ts +2 -0
- package/dist/C_Markdown.js +3 -0
- package/dist/C_Markdown2.js +186 -0
- package/dist/C_Markdown2.js.map +1 -0
- package/dist/C_NotificationCenter-0l3TY2Gn.css.map +1 -0
- package/dist/C_NotificationCenter.cjs +20 -0
- package/dist/C_NotificationCenter.d.cts +2 -0
- package/dist/C_NotificationCenter.d.ts +2 -0
- package/dist/C_NotificationCenter.js +4 -0
- package/dist/C_NotificationCenter2.js +1383 -0
- package/dist/C_NotificationCenter2.js.map +1 -0
- package/dist/C_Progress.cjs +4 -0
- package/dist/C_Progress.d.cts +2 -0
- package/dist/C_Progress.d.ts +2 -0
- package/dist/C_Progress.js +3 -0
- package/dist/C_Progress2.js +103 -0
- package/dist/C_Progress2.js.map +1 -0
- package/dist/C_QRCode-DbdiAIPg.css.map +1 -0
- package/dist/C_QRCode.cjs +5 -0
- package/dist/C_QRCode.d.cts +2 -0
- package/dist/C_QRCode.d.ts +2 -0
- package/dist/C_QRCode.js +3 -0
- package/dist/C_QRCode2.js +218 -0
- package/dist/C_QRCode2.js.map +1 -0
- package/dist/C_Signature-zhHCbra9.css.map +1 -0
- package/dist/C_Signature.cjs +8 -0
- package/dist/C_Signature.d.cts +2 -0
- package/dist/C_Signature.d.ts +2 -0
- package/dist/C_Signature.js +4 -0
- package/dist/C_Signature2.js +618 -0
- package/dist/C_Signature2.js.map +1 -0
- package/dist/C_SplitPane-C6sBsfKY.css.map +1 -0
- package/dist/C_SplitPane.cjs +6 -0
- package/dist/C_SplitPane.d.cts +2 -0
- package/dist/C_SplitPane.d.ts +2 -0
- package/dist/C_SplitPane.js +4 -0
- package/dist/C_SplitPane2.js +356 -0
- package/dist/C_SplitPane2.js.map +1 -0
- package/dist/C_Steps-CODHN5Hs.css.map +1 -0
- package/dist/C_Steps.cjs +4 -0
- package/dist/C_Steps.d.cts +2 -0
- package/dist/C_Steps.d.ts +2 -0
- package/dist/C_Steps.js +3 -0
- package/dist/C_Steps2.js +82 -0
- package/dist/C_Steps2.js.map +1 -0
- package/dist/C_Table-DSNsntmT.css.map +1 -0
- package/dist/C_Table.cjs +19 -0
- package/dist/C_Table.d.cts +2 -0
- package/dist/C_Table.d.ts +2 -0
- package/dist/C_Table.js +5 -0
- package/dist/C_Table2.js +3009 -0
- package/dist/C_Table2.js.map +1 -0
- package/dist/C_Theme.cjs +4 -0
- package/dist/C_Theme.d.cts +2 -0
- package/dist/C_Theme.d.ts +2 -0
- package/dist/C_Theme.js +3 -0
- package/dist/C_Theme2.js +60 -0
- package/dist/C_Theme2.js.map +1 -0
- package/dist/C_Time-BvZLYraL.css.map +1 -0
- package/dist/C_Time.cjs +5 -0
- package/dist/C_Time.d.cts +2 -0
- package/dist/C_Time.d.ts +2 -0
- package/dist/C_Time.js +3 -0
- package/dist/C_Time2.js +199 -0
- package/dist/C_Time2.js.map +1 -0
- package/dist/C_Tree-0GDv--jX.css.map +1 -0
- package/dist/C_Tree.cjs +7 -0
- package/dist/C_Tree.d.cts +2 -0
- package/dist/C_Tree.d.ts +2 -0
- package/dist/C_Tree.js +4 -0
- package/dist/C_Tree2.js +441 -0
- package/dist/C_Tree2.js.map +1 -0
- package/dist/C_Upload-BXd3YYLx.css.map +1 -0
- package/dist/C_Upload.cjs +12 -0
- package/dist/C_Upload.d.cts +2 -0
- package/dist/C_Upload.d.ts +2 -0
- package/dist/C_Upload.js +4 -0
- package/dist/C_Upload2.js +1388 -0
- package/dist/C_Upload2.js.map +1 -0
- package/dist/C_VideoPlayer-DYG3RL0Q.css.map +1 -0
- package/dist/C_VideoPlayer.cjs +23 -0
- package/dist/C_VideoPlayer.d.cts +2 -0
- package/dist/C_VideoPlayer.d.ts +2 -0
- package/dist/C_VideoPlayer.js +3 -0
- package/dist/C_VideoPlayer2.js +1932 -0
- package/dist/C_VideoPlayer2.js.map +1 -0
- package/dist/C_VtableGantt-fhItIiHE.css.map +1 -0
- package/dist/C_VtableGantt.cjs +6 -0
- package/dist/C_VtableGantt.d.cts +2 -0
- package/dist/C_VtableGantt.d.ts +2 -0
- package/dist/C_VtableGantt.js +4 -0
- package/dist/C_VtableGantt2.js +873 -0
- package/dist/C_VtableGantt2.js.map +1 -0
- package/dist/C_WaterFall-8sQDFXKg.css.map +1 -0
- package/dist/C_WaterFall.cjs +13 -0
- package/dist/C_WaterFall.d.cts +2 -0
- package/dist/C_WaterFall.d.ts +2 -0
- package/dist/C_WaterFall.js +3 -0
- package/dist/C_WaterFall2.js +365 -0
- package/dist/C_WaterFall2.js.map +1 -0
- package/dist/C_WorkFlow-J-dyIuh9.css.map +1 -0
- package/dist/C_WorkFlow.cjs +8 -0
- package/dist/C_WorkFlow.d.cts +2 -0
- package/dist/C_WorkFlow.d.ts +2 -0
- package/dist/C_WorkFlow.js +4 -0
- package/dist/C_WorkFlow2.js +1984 -0
- package/dist/C_WorkFlow2.js.map +1 -0
- package/dist/chunk.js +22 -0
- package/dist/city.js +4817 -0
- package/dist/city.js.map +1 -0
- package/dist/constants.d.ts +273 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants2.d.ts +178 -0
- package/dist/constants2.d.ts.map +1 -0
- package/dist/constants3.d.ts +475 -0
- package/dist/constants3.d.ts.map +1 -0
- package/dist/constants4.d.ts +430 -0
- package/dist/constants4.d.ts.map +1 -0
- package/dist/constants5.d.ts +4283 -0
- package/dist/constants5.d.ts.map +1 -0
- package/dist/data.d.ts +67 -0
- package/dist/data.d.ts.map +1 -0
- package/dist/export-helper.js +9 -0
- package/dist/index.cjs +409 -0
- package/dist/index.d.cts +96 -0
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.ts +103 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +230 -0
- package/dist/index.js.map +1 -0
- package/dist/index.vue.d.ts +80 -0
- package/dist/index.vue.d.ts.map +1 -0
- package/dist/index10.vue.d.ts +72 -0
- package/dist/index10.vue.d.ts.map +1 -0
- package/dist/index11.vue.d.ts +26 -0
- package/dist/index11.vue.d.ts.map +1 -0
- package/dist/index12.vue.d.ts +81 -0
- package/dist/index12.vue.d.ts.map +1 -0
- package/dist/index13.vue.d.ts +55 -0
- package/dist/index13.vue.d.ts.map +1 -0
- package/dist/index14.vue.d.ts +33 -0
- package/dist/index14.vue.d.ts.map +1 -0
- package/dist/index15.vue.d.ts +18 -0
- package/dist/index15.vue.d.ts.map +1 -0
- package/dist/index16.vue.d.ts +662 -0
- package/dist/index16.vue.d.ts.map +1 -0
- package/dist/index2.vue.d.ts +38 -0
- package/dist/index2.vue.d.ts.map +1 -0
- package/dist/index3.vue.d.ts +45 -0
- package/dist/index3.vue.d.ts.map +1 -0
- package/dist/index4.vue.d.ts +31 -0
- package/dist/index4.vue.d.ts.map +1 -0
- package/dist/index5.vue.d.ts +35 -0
- package/dist/index5.vue.d.ts.map +1 -0
- package/dist/index6.vue.d.ts +48 -0
- package/dist/index6.vue.d.ts.map +1 -0
- package/dist/index7.vue.d.ts +56 -0
- package/dist/index7.vue.d.ts.map +1 -0
- package/dist/index8.vue.d.ts +41 -0
- package/dist/index8.vue.d.ts.map +1 -0
- package/dist/index9.vue.d.ts +30 -0
- package/dist/index9.vue.d.ts.map +1 -0
- package/dist/storage.js +31 -0
- package/dist/storage.js.map +1 -0
- package/dist/style.css +7725 -0
- package/dist/useCalendarEvents.d.ts +148 -0
- package/dist/useCalendarEvents.d.ts.map +1 -0
- package/dist/useCollapsePanel.d.ts +132 -0
- package/dist/useCollapsePanel.d.ts.map +1 -0
- package/dist/useCropperCore.d.ts +102 -0
- package/dist/useCropperCore.d.ts.map +1 -0
- package/dist/useDraggableLayout.d.ts +194 -0
- package/dist/useDraggableLayout.d.ts.map +1 -0
- package/dist/useDynamicFormState.d.ts +4248 -0
- package/dist/useDynamicFormState.d.ts.map +1 -0
- package/dist/useEdgeInteraction.d.ts +7614 -0
- package/dist/useEdgeInteraction.d.ts.map +1 -0
- package/dist/useFullscreen.d.ts +166 -0
- package/dist/useFullscreen.d.ts.map +1 -0
- package/dist/useInfiniteScroll.d.ts +169 -0
- package/dist/useInfiniteScroll.d.ts.map +1 -0
- package/dist/useModalEdit.d.ts +960 -0
- package/dist/useModalEdit.d.ts.map +1 -0
- package/dist/useQRCode.d.ts +87 -0
- package/dist/useQRCode.d.ts.map +1 -0
- package/dist/useSearchState.d.ts +180 -0
- package/dist/useSearchState.d.ts.map +1 -0
- package/dist/useSignatureHistory.d.ts +189 -0
- package/dist/useSignatureHistory.d.ts.map +1 -0
- package/dist/useSplitResize.d.ts +158 -0
- package/dist/useSplitResize.d.ts.map +1 -0
- package/dist/useTimeSelection.d.ts +105 -0
- package/dist/useTimeSelection.d.ts.map +1 -0
- package/dist/useTreeOperations.d.ts +183 -0
- package/dist/useTreeOperations.d.ts.map +1 -0
- package/dist/useWorkflowValidation.d.ts +1052 -0
- package/dist/useWorkflowValidation.d.ts.map +1 -0
- package/package.json +342 -0
|
@@ -0,0 +1 @@
|
|
|
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/PdfViewer/index.vue","../src/components/C_FilePreview/components/WordViewer/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/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","../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","<!--\r\n PdfViewer — PDF 文件预览子组件\r\n 负责: 工具栏(翻页+缩放) + iframe 渲染\r\n-->\r\n<template>\r\n <div class=\"file-container pdf-container\">\r\n <div class=\"file-toolbar\">\r\n <div class=\"flex justify-between items-center\">\r\n <!-- 翻页控制 -->\r\n <div class=\"flex gap-2 items-center\">\r\n <NButton\r\n size=\"small\"\r\n :disabled=\"currentPage <= 1\"\r\n @click=\"changePage('prev')\"\r\n >\r\n <template #icon>\r\n <C_Icon name=\"ic:outline-chevron-left\" />\r\n </template>\r\n </NButton>\r\n <NInputNumber\r\n v-model:value=\"currentPage\"\r\n size=\"small\"\r\n :min=\"1\"\r\n :max=\"totalPages\"\r\n style=\"width: 80px\"\r\n @update:value=\"changePage\"\r\n />\r\n <span class=\"text-sm text-gray-600\">/ {{ totalPages }}</span>\r\n <NButton\r\n size=\"small\"\r\n :disabled=\"currentPage >= totalPages\"\r\n @click=\"changePage('next')\"\r\n >\r\n <template #icon>\r\n <C_Icon name=\"ic:outline-chevron-right\" />\r\n </template>\r\n </NButton>\r\n </div>\r\n\r\n <!-- 缩放控制 -->\r\n <div class=\"flex gap-2 items-center\">\r\n <NButton\r\n size=\"small\"\r\n :disabled=\"scale <= 0.5\"\r\n @click=\"adjustZoom('out')\"\r\n >\r\n <template #icon>\r\n <C_Icon name=\"ic:outline-zoom-out\" />\r\n </template>\r\n </NButton>\r\n <span class=\"text-sm text-gray-600 min-w-12 text-center\">\r\n {{ Math.round(scale * 100) }}%\r\n </span>\r\n <NButton\r\n size=\"small\"\r\n :disabled=\"scale >= 3\"\r\n @click=\"adjustZoom('in')\"\r\n >\r\n <template #icon>\r\n <C_Icon name=\"ic:outline-zoom-in\" />\r\n </template>\r\n </NButton>\r\n <NButton size=\"small\" @click=\"adjustZoom('reset')\">\r\n <template #icon>\r\n <C_Icon name=\"ic:outline-fit-screen\" />\r\n </template>\r\n 适应\r\n </NButton>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"file-viewer\">\r\n <iframe\r\n v-if=\"pdfUrl\"\r\n :src=\"pdfUrl\"\r\n class=\"w-full h-full border-0\"\r\n title=\"PDF预览\"\r\n frameborder=\"0\"\r\n allowfullscreen\r\n />\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref } from \"vue\";\r\nimport { NButton, NInputNumber } from \"naive-ui\";\r\nimport { createZoomHandler, ZOOM_CONFIGS } from \"../../data\";\r\n\r\nconst props = defineProps<{\r\n pdfUrl: string;\r\n totalPages: number;\r\n}>();\r\n\r\nconst currentPage = ref(1);\r\nconst scale = ref(1);\r\n\r\nconst adjustZoom = createZoomHandler(scale, ZOOM_CONFIGS.pdf);\r\n\r\nconst changePage = (action: \"prev\" | \"next\" | number) => {\r\n if (typeof action === \"number\") {\r\n currentPage.value = Math.max(1, Math.min(action, props.totalPages));\r\n } else {\r\n const delta = action === \"prev\" ? -1 : 1;\r\n currentPage.value = Math.max(\r\n 1,\r\n Math.min(currentPage.value + delta, props.totalPages),\r\n );\r\n }\r\n};\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n@use \"./index.scss\";\r\n</style>\r\n","<!--\r\n PdfViewer — PDF 文件预览子组件\r\n 负责: 工具栏(翻页+缩放) + iframe 渲染\r\n-->\r\n<template>\r\n <div class=\"file-container pdf-container\">\r\n <div class=\"file-toolbar\">\r\n <div class=\"flex justify-between items-center\">\r\n <!-- 翻页控制 -->\r\n <div class=\"flex gap-2 items-center\">\r\n <NButton\r\n size=\"small\"\r\n :disabled=\"currentPage <= 1\"\r\n @click=\"changePage('prev')\"\r\n >\r\n <template #icon>\r\n <C_Icon name=\"ic:outline-chevron-left\" />\r\n </template>\r\n </NButton>\r\n <NInputNumber\r\n v-model:value=\"currentPage\"\r\n size=\"small\"\r\n :min=\"1\"\r\n :max=\"totalPages\"\r\n style=\"width: 80px\"\r\n @update:value=\"changePage\"\r\n />\r\n <span class=\"text-sm text-gray-600\">/ {{ totalPages }}</span>\r\n <NButton\r\n size=\"small\"\r\n :disabled=\"currentPage >= totalPages\"\r\n @click=\"changePage('next')\"\r\n >\r\n <template #icon>\r\n <C_Icon name=\"ic:outline-chevron-right\" />\r\n </template>\r\n </NButton>\r\n </div>\r\n\r\n <!-- 缩放控制 -->\r\n <div class=\"flex gap-2 items-center\">\r\n <NButton\r\n size=\"small\"\r\n :disabled=\"scale <= 0.5\"\r\n @click=\"adjustZoom('out')\"\r\n >\r\n <template #icon>\r\n <C_Icon name=\"ic:outline-zoom-out\" />\r\n </template>\r\n </NButton>\r\n <span class=\"text-sm text-gray-600 min-w-12 text-center\">\r\n {{ Math.round(scale * 100) }}%\r\n </span>\r\n <NButton\r\n size=\"small\"\r\n :disabled=\"scale >= 3\"\r\n @click=\"adjustZoom('in')\"\r\n >\r\n <template #icon>\r\n <C_Icon name=\"ic:outline-zoom-in\" />\r\n </template>\r\n </NButton>\r\n <NButton size=\"small\" @click=\"adjustZoom('reset')\">\r\n <template #icon>\r\n <C_Icon name=\"ic:outline-fit-screen\" />\r\n </template>\r\n 适应\r\n </NButton>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"file-viewer\">\r\n <iframe\r\n v-if=\"pdfUrl\"\r\n :src=\"pdfUrl\"\r\n class=\"w-full h-full border-0\"\r\n title=\"PDF预览\"\r\n frameborder=\"0\"\r\n allowfullscreen\r\n />\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref } from \"vue\";\r\nimport { NButton, NInputNumber } from \"naive-ui\";\r\nimport { createZoomHandler, ZOOM_CONFIGS } from \"../../data\";\r\n\r\nconst props = defineProps<{\r\n pdfUrl: string;\r\n totalPages: number;\r\n}>();\r\n\r\nconst currentPage = ref(1);\r\nconst scale = ref(1);\r\n\r\nconst adjustZoom = createZoomHandler(scale, ZOOM_CONFIGS.pdf);\r\n\r\nconst changePage = (action: \"prev\" | \"next\" | number) => {\r\n if (typeof action === \"number\") {\r\n currentPage.value = Math.max(1, Math.min(action, props.totalPages));\r\n } else {\r\n const delta = action === \"prev\" ? -1 : 1;\r\n currentPage.value = Math.max(\r\n 1,\r\n Math.min(currentPage.value + delta, props.totalPages),\r\n );\r\n }\r\n};\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n@use \"./index.scss\";\r\n</style>\r\n","<!--\r\n PdfViewer — PDF 文件预览子组件\r\n 负责: 工具栏(翻页+缩放) + iframe 渲染\r\n-->\r\n<template>\r\n <div class=\"file-container pdf-container\">\r\n <div class=\"file-toolbar\">\r\n <div class=\"flex justify-between items-center\">\r\n <!-- 翻页控制 -->\r\n <div class=\"flex gap-2 items-center\">\r\n <NButton\r\n size=\"small\"\r\n :disabled=\"currentPage <= 1\"\r\n @click=\"changePage('prev')\"\r\n >\r\n <template #icon>\r\n <C_Icon name=\"ic:outline-chevron-left\" />\r\n </template>\r\n </NButton>\r\n <NInputNumber\r\n v-model:value=\"currentPage\"\r\n size=\"small\"\r\n :min=\"1\"\r\n :max=\"totalPages\"\r\n style=\"width: 80px\"\r\n @update:value=\"changePage\"\r\n />\r\n <span class=\"text-sm text-gray-600\">/ {{ totalPages }}</span>\r\n <NButton\r\n size=\"small\"\r\n :disabled=\"currentPage >= totalPages\"\r\n @click=\"changePage('next')\"\r\n >\r\n <template #icon>\r\n <C_Icon name=\"ic:outline-chevron-right\" />\r\n </template>\r\n </NButton>\r\n </div>\r\n\r\n <!-- 缩放控制 -->\r\n <div class=\"flex gap-2 items-center\">\r\n <NButton\r\n size=\"small\"\r\n :disabled=\"scale <= 0.5\"\r\n @click=\"adjustZoom('out')\"\r\n >\r\n <template #icon>\r\n <C_Icon name=\"ic:outline-zoom-out\" />\r\n </template>\r\n </NButton>\r\n <span class=\"text-sm text-gray-600 min-w-12 text-center\">\r\n {{ Math.round(scale * 100) }}%\r\n </span>\r\n <NButton\r\n size=\"small\"\r\n :disabled=\"scale >= 3\"\r\n @click=\"adjustZoom('in')\"\r\n >\r\n <template #icon>\r\n <C_Icon name=\"ic:outline-zoom-in\" />\r\n </template>\r\n </NButton>\r\n <NButton size=\"small\" @click=\"adjustZoom('reset')\">\r\n <template #icon>\r\n <C_Icon name=\"ic:outline-fit-screen\" />\r\n </template>\r\n 适应\r\n </NButton>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"file-viewer\">\r\n <iframe\r\n v-if=\"pdfUrl\"\r\n :src=\"pdfUrl\"\r\n class=\"w-full h-full border-0\"\r\n title=\"PDF预览\"\r\n frameborder=\"0\"\r\n allowfullscreen\r\n />\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref } from \"vue\";\r\nimport { NButton, NInputNumber } from \"naive-ui\";\r\nimport { createZoomHandler, ZOOM_CONFIGS } from \"../../data\";\r\n\r\nconst props = defineProps<{\r\n pdfUrl: string;\r\n totalPages: number;\r\n}>();\r\n\r\nconst currentPage = ref(1);\r\nconst scale = ref(1);\r\n\r\nconst adjustZoom = createZoomHandler(scale, ZOOM_CONFIGS.pdf);\r\n\r\nconst changePage = (action: \"prev\" | \"next\" | number) => {\r\n if (typeof action === \"number\") {\r\n currentPage.value = Math.max(1, Math.min(action, props.totalPages));\r\n } else {\r\n const delta = action === \"prev\" ? -1 : 1;\r\n currentPage.value = Math.max(\r\n 1,\r\n Math.min(currentPage.value + delta, props.totalPages),\r\n );\r\n }\r\n};\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n@use \"./index.scss\";\r\n</style>\r\n","<!--\r\n WordViewer — Word 文档预览子组件\r\n 负责: 目录导航 + 缩放 + 文档内容渲染\r\n-->\r\n<template>\r\n <div class=\"file-container word-container\">\r\n <div class=\"file-toolbar\">\r\n <div class=\"flex gap-2 items-center\">\r\n <NButton size=\"small\" @click=\"showOutline = !showOutline\">\r\n <template #icon>\r\n <C_Icon name=\"ic:outline-list\" />\r\n </template>\r\n {{ showOutline ? \"隐藏\" : \"显示\" }}目录\r\n </NButton>\r\n <NDivider vertical />\r\n <NButton\r\n size=\"small\"\r\n :disabled=\"wordZoom <= 50\"\r\n @click=\"adjustWordZoom('out')\"\r\n >\r\n <template #icon>\r\n <C_Icon name=\"ic:outline-zoom-out\" />\r\n </template>\r\n </NButton>\r\n <span class=\"text-sm text-gray-600 min-w-12 text-center\">\r\n {{ wordZoom }}%\r\n </span>\r\n <NButton\r\n size=\"small\"\r\n :disabled=\"wordZoom >= 200\"\r\n @click=\"adjustWordZoom('in')\"\r\n >\r\n <template #icon>\r\n <C_Icon name=\"ic:outline-zoom-in\" />\r\n </template>\r\n </NButton>\r\n <NButton size=\"small\" @click=\"adjustWordZoom('reset')\">\r\n <template #icon>\r\n <C_Icon name=\"ic:outline-fit-screen\" />\r\n </template>\r\n 重置\r\n </NButton>\r\n </div>\r\n </div>\r\n\r\n <div class=\"word-layout\">\r\n <div class=\"word-main\">\r\n <!-- 侧边栏目录 -->\r\n <div v-if=\"showOutline\" class=\"word-outline\">\r\n <div class=\"outline-header\">\r\n <h3 class=\"text-sm font-semibold\">文档目录</h3>\r\n </div>\r\n <div class=\"outline-content\">\r\n <div\r\n v-for=\"(heading, index) in headings\"\r\n :key=\"index\"\r\n class=\"outline-item\"\r\n :class=\"`level-${heading.level}`\"\r\n @click=\"scrollToHeading(heading.id)\"\r\n >\r\n {{ heading.text }}\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- 主要内容区域 -->\r\n <div class=\"word-content\">\r\n <div\r\n class=\"word-document\"\r\n :style=\"{\r\n transform: `scale(${wordZoom / 100})`,\r\n transformOrigin: 'top center',\r\n }\"\r\n v-html=\"content\"\r\n ></div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref } from \"vue\";\r\nimport { NButton, NDivider } from \"naive-ui\";\r\nimport { createZoomHandler, ZOOM_CONFIGS } from \"../../data\";\r\nimport type { DocHeading } from \"../../types\";\r\n\r\ndefineProps<{\r\n content: string;\r\n headings: DocHeading[];\r\n}>();\r\n\r\nconst showOutline = ref(true);\r\nconst wordZoom = ref(100);\r\n\r\nconst adjustWordZoom = createZoomHandler(wordZoom, ZOOM_CONFIGS.word);\r\n\r\nconst scrollToHeading = (headingId: string) => {\r\n document\r\n .getElementById(headingId)\r\n ?.scrollIntoView({ behavior: \"smooth\", block: \"start\" });\r\n};\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n@use \"./index.scss\";\r\n</style>\r\n","<!--\r\n WordViewer — Word 文档预览子组件\r\n 负责: 目录导航 + 缩放 + 文档内容渲染\r\n-->\r\n<template>\r\n <div class=\"file-container word-container\">\r\n <div class=\"file-toolbar\">\r\n <div class=\"flex gap-2 items-center\">\r\n <NButton size=\"small\" @click=\"showOutline = !showOutline\">\r\n <template #icon>\r\n <C_Icon name=\"ic:outline-list\" />\r\n </template>\r\n {{ showOutline ? \"隐藏\" : \"显示\" }}目录\r\n </NButton>\r\n <NDivider vertical />\r\n <NButton\r\n size=\"small\"\r\n :disabled=\"wordZoom <= 50\"\r\n @click=\"adjustWordZoom('out')\"\r\n >\r\n <template #icon>\r\n <C_Icon name=\"ic:outline-zoom-out\" />\r\n </template>\r\n </NButton>\r\n <span class=\"text-sm text-gray-600 min-w-12 text-center\">\r\n {{ wordZoom }}%\r\n </span>\r\n <NButton\r\n size=\"small\"\r\n :disabled=\"wordZoom >= 200\"\r\n @click=\"adjustWordZoom('in')\"\r\n >\r\n <template #icon>\r\n <C_Icon name=\"ic:outline-zoom-in\" />\r\n </template>\r\n </NButton>\r\n <NButton size=\"small\" @click=\"adjustWordZoom('reset')\">\r\n <template #icon>\r\n <C_Icon name=\"ic:outline-fit-screen\" />\r\n </template>\r\n 重置\r\n </NButton>\r\n </div>\r\n </div>\r\n\r\n <div class=\"word-layout\">\r\n <div class=\"word-main\">\r\n <!-- 侧边栏目录 -->\r\n <div v-if=\"showOutline\" class=\"word-outline\">\r\n <div class=\"outline-header\">\r\n <h3 class=\"text-sm font-semibold\">文档目录</h3>\r\n </div>\r\n <div class=\"outline-content\">\r\n <div\r\n v-for=\"(heading, index) in headings\"\r\n :key=\"index\"\r\n class=\"outline-item\"\r\n :class=\"`level-${heading.level}`\"\r\n @click=\"scrollToHeading(heading.id)\"\r\n >\r\n {{ heading.text }}\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- 主要内容区域 -->\r\n <div class=\"word-content\">\r\n <div\r\n class=\"word-document\"\r\n :style=\"{\r\n transform: `scale(${wordZoom / 100})`,\r\n transformOrigin: 'top center',\r\n }\"\r\n v-html=\"content\"\r\n ></div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref } from \"vue\";\r\nimport { NButton, NDivider } from \"naive-ui\";\r\nimport { createZoomHandler, ZOOM_CONFIGS } from \"../../data\";\r\nimport type { DocHeading } from \"../../types\";\r\n\r\ndefineProps<{\r\n content: string;\r\n headings: DocHeading[];\r\n}>();\r\n\r\nconst showOutline = ref(true);\r\nconst wordZoom = ref(100);\r\n\r\nconst adjustWordZoom = createZoomHandler(wordZoom, ZOOM_CONFIGS.word);\r\n\r\nconst scrollToHeading = (headingId: string) => {\r\n document\r\n .getElementById(headingId)\r\n ?.scrollIntoView({ behavior: \"smooth\", block: \"start\" });\r\n};\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n@use \"./index.scss\";\r\n</style>\r\n","<!--\r\n WordViewer — Word 文档预览子组件\r\n 负责: 目录导航 + 缩放 + 文档内容渲染\r\n-->\r\n<template>\r\n <div class=\"file-container word-container\">\r\n <div class=\"file-toolbar\">\r\n <div class=\"flex gap-2 items-center\">\r\n <NButton size=\"small\" @click=\"showOutline = !showOutline\">\r\n <template #icon>\r\n <C_Icon name=\"ic:outline-list\" />\r\n </template>\r\n {{ showOutline ? \"隐藏\" : \"显示\" }}目录\r\n </NButton>\r\n <NDivider vertical />\r\n <NButton\r\n size=\"small\"\r\n :disabled=\"wordZoom <= 50\"\r\n @click=\"adjustWordZoom('out')\"\r\n >\r\n <template #icon>\r\n <C_Icon name=\"ic:outline-zoom-out\" />\r\n </template>\r\n </NButton>\r\n <span class=\"text-sm text-gray-600 min-w-12 text-center\">\r\n {{ wordZoom }}%\r\n </span>\r\n <NButton\r\n size=\"small\"\r\n :disabled=\"wordZoom >= 200\"\r\n @click=\"adjustWordZoom('in')\"\r\n >\r\n <template #icon>\r\n <C_Icon name=\"ic:outline-zoom-in\" />\r\n </template>\r\n </NButton>\r\n <NButton size=\"small\" @click=\"adjustWordZoom('reset')\">\r\n <template #icon>\r\n <C_Icon name=\"ic:outline-fit-screen\" />\r\n </template>\r\n 重置\r\n </NButton>\r\n </div>\r\n </div>\r\n\r\n <div class=\"word-layout\">\r\n <div class=\"word-main\">\r\n <!-- 侧边栏目录 -->\r\n <div v-if=\"showOutline\" class=\"word-outline\">\r\n <div class=\"outline-header\">\r\n <h3 class=\"text-sm font-semibold\">文档目录</h3>\r\n </div>\r\n <div class=\"outline-content\">\r\n <div\r\n v-for=\"(heading, index) in headings\"\r\n :key=\"index\"\r\n class=\"outline-item\"\r\n :class=\"`level-${heading.level}`\"\r\n @click=\"scrollToHeading(heading.id)\"\r\n >\r\n {{ heading.text }}\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- 主要内容区域 -->\r\n <div class=\"word-content\">\r\n <div\r\n class=\"word-document\"\r\n :style=\"{\r\n transform: `scale(${wordZoom / 100})`,\r\n transformOrigin: 'top center',\r\n }\"\r\n v-html=\"content\"\r\n ></div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref } from \"vue\";\r\nimport { NButton, NDivider } from \"naive-ui\";\r\nimport { createZoomHandler, ZOOM_CONFIGS } from \"../../data\";\r\nimport type { DocHeading } from \"../../types\";\r\n\r\ndefineProps<{\r\n content: string;\r\n headings: DocHeading[];\r\n}>();\r\n\r\nconst showOutline = ref(true);\r\nconst wordZoom = ref(100);\r\n\r\nconst adjustWordZoom = createZoomHandler(wordZoom, ZOOM_CONFIGS.word);\r\n\r\nconst scrollToHeading = (headingId: string) => {\r\n document\r\n .getElementById(headingId)\r\n ?.scrollIntoView({ behavior: \"smooth\", block: \"start\" });\r\n};\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n@use \"./index.scss\";\r\n</style>\r\n","<!--\r\n ExcelViewer — Excel 表格预览子组件\r\n 负责: 工作表切换 + 表格渲染(合并单元格) + 分页 + 格式切换\r\n-->\r\n<template>\r\n <div class=\"file-container excel-container\">\r\n <!-- 工具栏 -->\r\n <div class=\"file-toolbar\">\r\n <div class=\"flex justify-between items-center\">\r\n <div class=\"flex gap-2 items-center\">\r\n <NTabs\r\n v-if=\"sheets.length > 1\"\r\n v-model:value=\"activeSheet\"\r\n type=\"card\"\r\n size=\"small\"\r\n >\r\n <NTabPane\r\n v-for=\"sheet in sheets\"\r\n :key=\"sheet.name\"\r\n :name=\"sheet.name\"\r\n :tab=\"sheet.name\"\r\n />\r\n </NTabs>\r\n <span v-else class=\"text-sm text-gray-600\">\r\n 工作表: {{ activeSheet }}\r\n </span>\r\n </div>\r\n\r\n <div class=\"flex gap-2 items-center\">\r\n <NButton size=\"small\" @click=\"showExcelFormat = !showExcelFormat\">\r\n <template #icon>\r\n <C_Icon name=\"ic:outline-format-paint\" />\r\n </template>\r\n {{ showExcelFormat ? \"紧凑视图\" : \"完整格式\" }}\r\n </NButton>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"excel-viewer\">\r\n <!-- 信息面板 -->\r\n <div v-if=\"currentData.length > 0\" class=\"excel-info\">\r\n <NText depth=\"3\" class=\"text-sm\">\r\n 当前工作表: {{ activeSheet }} | 总行数: {{ currentData.length }} |\r\n 总列数: {{ currentColumns.length }} | 当前页:\r\n {{ currentExcelPage }}/{{ totalExcelPages }}\r\n </NText>\r\n </div>\r\n\r\n <!-- 表格 -->\r\n <div class=\"excel-table-container\">\r\n <div\r\n class=\"excel-table-wrapper\"\r\n :class=\"{ 'simple-mode': !showExcelFormat }\"\r\n >\r\n <table v-if=\"currentData.length > 0\" class=\"excel-table\">\r\n <thead>\r\n <tr>\r\n <th class=\"row-number\">行号</th>\r\n <th\r\n v-for=\"(col, index) in currentColumns\"\r\n :key=\"col.key\"\r\n class=\"excel-header\"\r\n :style=\"{ minWidth: col.width + 'px' }\"\r\n >\r\n <div class=\"header-content\">\r\n <span class=\"column-letter\">{{\r\n getColumnLetter(index)\r\n }}</span>\r\n <span class=\"column-title\">{{ col.title }}</span>\r\n </div>\r\n </th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n <tr\r\n v-for=\"(row, rowIndex) in paginatedData\"\r\n :key=\"rowIndex\"\r\n class=\"excel-row\"\r\n >\r\n <td class=\"row-number\">\r\n {{ (currentExcelPage - 1) * pageSize + rowIndex + 1 }}\r\n </td>\r\n <td\r\n v-for=\"col in currentColumns\"\r\n :key=\"col.key\"\r\n v-show=\"!row[col.key]?.hidden\"\r\n class=\"excel-cell\"\r\n :class=\"[\r\n getCellClass(row[col.key]?.value),\r\n row[col.key]?.merged ? 'merged-cell' : '',\r\n !showExcelFormat ? 'compact-cell' : '',\r\n ]\"\r\n :rowspan=\"row[col.key]?.rowspan || 1\"\r\n :colspan=\"row[col.key]?.colspan || 1\"\r\n :title=\"row[col.key]?.value\"\r\n >\r\n {{ formatCellValue(row[col.key]?.value) }}\r\n </td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n\r\n <div v-else class=\"excel-empty\">\r\n <NEmpty description=\"该工作表没有数据或解析失败\">\r\n <template #extra>\r\n <NButton size=\"small\" @click=\"$emit('reload')\">\r\n 重新解析\r\n </NButton>\r\n </template>\r\n </NEmpty>\r\n </div>\r\n </div>\r\n\r\n <!-- 分页 -->\r\n <div v-if=\"totalExcelPages > 1\" class=\"excel-pagination\">\r\n <NPagination\r\n v-model:page=\"currentExcelPage\"\r\n :page-count=\"totalExcelPages\"\r\n :page-size=\"pageSize\"\r\n show-size-picker\r\n :page-sizes=\"PAGE_SIZE_OPTIONS\"\r\n @update:page-size=\"handlePageSizeChange\"\r\n />\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref, computed, watch } from \"vue\";\r\nimport { NButton, NTabs, NTabPane, NText, NEmpty, NPagination } from \"naive-ui\";\r\nimport {\r\n getColumnLetter,\r\n formatCellValue,\r\n getCellClass,\r\n PAGE_SIZE_OPTIONS,\r\n} from \"../../data\";\r\nimport type { ExcelSheet, ExcelRow, ExcelColumn } from \"../../types\";\r\n\r\nconst props = defineProps<{\r\n sheets: ExcelSheet[];\r\n}>();\r\n\r\ndefineEmits<{\r\n reload: [];\r\n}>();\r\n\r\n/* ==================== 内部状态 ==================== */\r\nconst activeSheet = ref(\"\");\r\nconst showExcelFormat = ref(false);\r\nconst currentExcelPage = ref(1);\r\nconst pageSize = ref(50);\r\n\r\n/* ==================== 当前工作表数据 ==================== */\r\nconst currentData = ref<ExcelRow[]>([]);\r\nconst currentColumns = ref<ExcelColumn[]>([]);\r\n\r\n/* ==================== 计算属性 ==================== */\r\nconst totalExcelPages = computed(() =>\r\n Math.ceil(currentData.value.length / pageSize.value),\r\n);\r\n\r\nconst paginatedData = computed(() => {\r\n const start = (currentExcelPage.value - 1) * pageSize.value;\r\n return currentData.value.slice(start, start + pageSize.value);\r\n});\r\n\r\n/* ==================== 方法 ==================== */\r\nconst handlePageSizeChange = (newPageSize: number) => {\r\n pageSize.value = newPageSize;\r\n currentExcelPage.value = 1;\r\n};\r\n\r\nconst syncSheetData = (sheetName: string) => {\r\n const sheet = props.sheets.find((s) => s.name === sheetName);\r\n if (sheet) {\r\n currentData.value = sheet.data;\r\n currentColumns.value = sheet.columns;\r\n currentExcelPage.value = 1;\r\n }\r\n};\r\n\r\n/* ==================== 监听器 ==================== */\r\nwatch(activeSheet, (newSheet) => {\r\n syncSheetData(newSheet);\r\n});\r\n\r\n/* sheets 变化时初始化 */\r\nwatch(\r\n () => props.sheets,\r\n (newSheets) => {\r\n if (newSheets.length > 0) {\r\n const [firstSheet] = newSheets;\r\n activeSheet.value = firstSheet.name;\r\n currentData.value = firstSheet.data;\r\n currentColumns.value = firstSheet.columns;\r\n currentExcelPage.value = 1;\r\n }\r\n },\r\n { immediate: true },\r\n);\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n@use \"./index.scss\";\r\n</style>\r\n","<!--\r\n ExcelViewer — Excel 表格预览子组件\r\n 负责: 工作表切换 + 表格渲染(合并单元格) + 分页 + 格式切换\r\n-->\r\n<template>\r\n <div class=\"file-container excel-container\">\r\n <!-- 工具栏 -->\r\n <div class=\"file-toolbar\">\r\n <div class=\"flex justify-between items-center\">\r\n <div class=\"flex gap-2 items-center\">\r\n <NTabs\r\n v-if=\"sheets.length > 1\"\r\n v-model:value=\"activeSheet\"\r\n type=\"card\"\r\n size=\"small\"\r\n >\r\n <NTabPane\r\n v-for=\"sheet in sheets\"\r\n :key=\"sheet.name\"\r\n :name=\"sheet.name\"\r\n :tab=\"sheet.name\"\r\n />\r\n </NTabs>\r\n <span v-else class=\"text-sm text-gray-600\">\r\n 工作表: {{ activeSheet }}\r\n </span>\r\n </div>\r\n\r\n <div class=\"flex gap-2 items-center\">\r\n <NButton size=\"small\" @click=\"showExcelFormat = !showExcelFormat\">\r\n <template #icon>\r\n <C_Icon name=\"ic:outline-format-paint\" />\r\n </template>\r\n {{ showExcelFormat ? \"紧凑视图\" : \"完整格式\" }}\r\n </NButton>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"excel-viewer\">\r\n <!-- 信息面板 -->\r\n <div v-if=\"currentData.length > 0\" class=\"excel-info\">\r\n <NText depth=\"3\" class=\"text-sm\">\r\n 当前工作表: {{ activeSheet }} | 总行数: {{ currentData.length }} |\r\n 总列数: {{ currentColumns.length }} | 当前页:\r\n {{ currentExcelPage }}/{{ totalExcelPages }}\r\n </NText>\r\n </div>\r\n\r\n <!-- 表格 -->\r\n <div class=\"excel-table-container\">\r\n <div\r\n class=\"excel-table-wrapper\"\r\n :class=\"{ 'simple-mode': !showExcelFormat }\"\r\n >\r\n <table v-if=\"currentData.length > 0\" class=\"excel-table\">\r\n <thead>\r\n <tr>\r\n <th class=\"row-number\">行号</th>\r\n <th\r\n v-for=\"(col, index) in currentColumns\"\r\n :key=\"col.key\"\r\n class=\"excel-header\"\r\n :style=\"{ minWidth: col.width + 'px' }\"\r\n >\r\n <div class=\"header-content\">\r\n <span class=\"column-letter\">{{\r\n getColumnLetter(index)\r\n }}</span>\r\n <span class=\"column-title\">{{ col.title }}</span>\r\n </div>\r\n </th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n <tr\r\n v-for=\"(row, rowIndex) in paginatedData\"\r\n :key=\"rowIndex\"\r\n class=\"excel-row\"\r\n >\r\n <td class=\"row-number\">\r\n {{ (currentExcelPage - 1) * pageSize + rowIndex + 1 }}\r\n </td>\r\n <td\r\n v-for=\"col in currentColumns\"\r\n :key=\"col.key\"\r\n v-show=\"!row[col.key]?.hidden\"\r\n class=\"excel-cell\"\r\n :class=\"[\r\n getCellClass(row[col.key]?.value),\r\n row[col.key]?.merged ? 'merged-cell' : '',\r\n !showExcelFormat ? 'compact-cell' : '',\r\n ]\"\r\n :rowspan=\"row[col.key]?.rowspan || 1\"\r\n :colspan=\"row[col.key]?.colspan || 1\"\r\n :title=\"row[col.key]?.value\"\r\n >\r\n {{ formatCellValue(row[col.key]?.value) }}\r\n </td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n\r\n <div v-else class=\"excel-empty\">\r\n <NEmpty description=\"该工作表没有数据或解析失败\">\r\n <template #extra>\r\n <NButton size=\"small\" @click=\"$emit('reload')\">\r\n 重新解析\r\n </NButton>\r\n </template>\r\n </NEmpty>\r\n </div>\r\n </div>\r\n\r\n <!-- 分页 -->\r\n <div v-if=\"totalExcelPages > 1\" class=\"excel-pagination\">\r\n <NPagination\r\n v-model:page=\"currentExcelPage\"\r\n :page-count=\"totalExcelPages\"\r\n :page-size=\"pageSize\"\r\n show-size-picker\r\n :page-sizes=\"PAGE_SIZE_OPTIONS\"\r\n @update:page-size=\"handlePageSizeChange\"\r\n />\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref, computed, watch } from \"vue\";\r\nimport { NButton, NTabs, NTabPane, NText, NEmpty, NPagination } from \"naive-ui\";\r\nimport {\r\n getColumnLetter,\r\n formatCellValue,\r\n getCellClass,\r\n PAGE_SIZE_OPTIONS,\r\n} from \"../../data\";\r\nimport type { ExcelSheet, ExcelRow, ExcelColumn } from \"../../types\";\r\n\r\nconst props = defineProps<{\r\n sheets: ExcelSheet[];\r\n}>();\r\n\r\ndefineEmits<{\r\n reload: [];\r\n}>();\r\n\r\n/* ==================== 内部状态 ==================== */\r\nconst activeSheet = ref(\"\");\r\nconst showExcelFormat = ref(false);\r\nconst currentExcelPage = ref(1);\r\nconst pageSize = ref(50);\r\n\r\n/* ==================== 当前工作表数据 ==================== */\r\nconst currentData = ref<ExcelRow[]>([]);\r\nconst currentColumns = ref<ExcelColumn[]>([]);\r\n\r\n/* ==================== 计算属性 ==================== */\r\nconst totalExcelPages = computed(() =>\r\n Math.ceil(currentData.value.length / pageSize.value),\r\n);\r\n\r\nconst paginatedData = computed(() => {\r\n const start = (currentExcelPage.value - 1) * pageSize.value;\r\n return currentData.value.slice(start, start + pageSize.value);\r\n});\r\n\r\n/* ==================== 方法 ==================== */\r\nconst handlePageSizeChange = (newPageSize: number) => {\r\n pageSize.value = newPageSize;\r\n currentExcelPage.value = 1;\r\n};\r\n\r\nconst syncSheetData = (sheetName: string) => {\r\n const sheet = props.sheets.find((s) => s.name === sheetName);\r\n if (sheet) {\r\n currentData.value = sheet.data;\r\n currentColumns.value = sheet.columns;\r\n currentExcelPage.value = 1;\r\n }\r\n};\r\n\r\n/* ==================== 监听器 ==================== */\r\nwatch(activeSheet, (newSheet) => {\r\n syncSheetData(newSheet);\r\n});\r\n\r\n/* sheets 变化时初始化 */\r\nwatch(\r\n () => props.sheets,\r\n (newSheets) => {\r\n if (newSheets.length > 0) {\r\n const [firstSheet] = newSheets;\r\n activeSheet.value = firstSheet.name;\r\n currentData.value = firstSheet.data;\r\n currentColumns.value = firstSheet.columns;\r\n currentExcelPage.value = 1;\r\n }\r\n },\r\n { immediate: true },\r\n);\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n@use \"./index.scss\";\r\n</style>\r\n","<!--\r\n ExcelViewer — Excel 表格预览子组件\r\n 负责: 工作表切换 + 表格渲染(合并单元格) + 分页 + 格式切换\r\n-->\r\n<template>\r\n <div class=\"file-container excel-container\">\r\n <!-- 工具栏 -->\r\n <div class=\"file-toolbar\">\r\n <div class=\"flex justify-between items-center\">\r\n <div class=\"flex gap-2 items-center\">\r\n <NTabs\r\n v-if=\"sheets.length > 1\"\r\n v-model:value=\"activeSheet\"\r\n type=\"card\"\r\n size=\"small\"\r\n >\r\n <NTabPane\r\n v-for=\"sheet in sheets\"\r\n :key=\"sheet.name\"\r\n :name=\"sheet.name\"\r\n :tab=\"sheet.name\"\r\n />\r\n </NTabs>\r\n <span v-else class=\"text-sm text-gray-600\">\r\n 工作表: {{ activeSheet }}\r\n </span>\r\n </div>\r\n\r\n <div class=\"flex gap-2 items-center\">\r\n <NButton size=\"small\" @click=\"showExcelFormat = !showExcelFormat\">\r\n <template #icon>\r\n <C_Icon name=\"ic:outline-format-paint\" />\r\n </template>\r\n {{ showExcelFormat ? \"紧凑视图\" : \"完整格式\" }}\r\n </NButton>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"excel-viewer\">\r\n <!-- 信息面板 -->\r\n <div v-if=\"currentData.length > 0\" class=\"excel-info\">\r\n <NText depth=\"3\" class=\"text-sm\">\r\n 当前工作表: {{ activeSheet }} | 总行数: {{ currentData.length }} |\r\n 总列数: {{ currentColumns.length }} | 当前页:\r\n {{ currentExcelPage }}/{{ totalExcelPages }}\r\n </NText>\r\n </div>\r\n\r\n <!-- 表格 -->\r\n <div class=\"excel-table-container\">\r\n <div\r\n class=\"excel-table-wrapper\"\r\n :class=\"{ 'simple-mode': !showExcelFormat }\"\r\n >\r\n <table v-if=\"currentData.length > 0\" class=\"excel-table\">\r\n <thead>\r\n <tr>\r\n <th class=\"row-number\">行号</th>\r\n <th\r\n v-for=\"(col, index) in currentColumns\"\r\n :key=\"col.key\"\r\n class=\"excel-header\"\r\n :style=\"{ minWidth: col.width + 'px' }\"\r\n >\r\n <div class=\"header-content\">\r\n <span class=\"column-letter\">{{\r\n getColumnLetter(index)\r\n }}</span>\r\n <span class=\"column-title\">{{ col.title }}</span>\r\n </div>\r\n </th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n <tr\r\n v-for=\"(row, rowIndex) in paginatedData\"\r\n :key=\"rowIndex\"\r\n class=\"excel-row\"\r\n >\r\n <td class=\"row-number\">\r\n {{ (currentExcelPage - 1) * pageSize + rowIndex + 1 }}\r\n </td>\r\n <td\r\n v-for=\"col in currentColumns\"\r\n :key=\"col.key\"\r\n v-show=\"!row[col.key]?.hidden\"\r\n class=\"excel-cell\"\r\n :class=\"[\r\n getCellClass(row[col.key]?.value),\r\n row[col.key]?.merged ? 'merged-cell' : '',\r\n !showExcelFormat ? 'compact-cell' : '',\r\n ]\"\r\n :rowspan=\"row[col.key]?.rowspan || 1\"\r\n :colspan=\"row[col.key]?.colspan || 1\"\r\n :title=\"row[col.key]?.value\"\r\n >\r\n {{ formatCellValue(row[col.key]?.value) }}\r\n </td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n\r\n <div v-else class=\"excel-empty\">\r\n <NEmpty description=\"该工作表没有数据或解析失败\">\r\n <template #extra>\r\n <NButton size=\"small\" @click=\"$emit('reload')\">\r\n 重新解析\r\n </NButton>\r\n </template>\r\n </NEmpty>\r\n </div>\r\n </div>\r\n\r\n <!-- 分页 -->\r\n <div v-if=\"totalExcelPages > 1\" class=\"excel-pagination\">\r\n <NPagination\r\n v-model:page=\"currentExcelPage\"\r\n :page-count=\"totalExcelPages\"\r\n :page-size=\"pageSize\"\r\n show-size-picker\r\n :page-sizes=\"PAGE_SIZE_OPTIONS\"\r\n @update:page-size=\"handlePageSizeChange\"\r\n />\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref, computed, watch } from \"vue\";\r\nimport { NButton, NTabs, NTabPane, NText, NEmpty, NPagination } from \"naive-ui\";\r\nimport {\r\n getColumnLetter,\r\n formatCellValue,\r\n getCellClass,\r\n PAGE_SIZE_OPTIONS,\r\n} from \"../../data\";\r\nimport type { ExcelSheet, ExcelRow, ExcelColumn } from \"../../types\";\r\n\r\nconst props = defineProps<{\r\n sheets: ExcelSheet[];\r\n}>();\r\n\r\ndefineEmits<{\r\n reload: [];\r\n}>();\r\n\r\n/* ==================== 内部状态 ==================== */\r\nconst activeSheet = ref(\"\");\r\nconst showExcelFormat = ref(false);\r\nconst currentExcelPage = ref(1);\r\nconst pageSize = ref(50);\r\n\r\n/* ==================== 当前工作表数据 ==================== */\r\nconst currentData = ref<ExcelRow[]>([]);\r\nconst currentColumns = ref<ExcelColumn[]>([]);\r\n\r\n/* ==================== 计算属性 ==================== */\r\nconst totalExcelPages = computed(() =>\r\n Math.ceil(currentData.value.length / pageSize.value),\r\n);\r\n\r\nconst paginatedData = computed(() => {\r\n const start = (currentExcelPage.value - 1) * pageSize.value;\r\n return currentData.value.slice(start, start + pageSize.value);\r\n});\r\n\r\n/* ==================== 方法 ==================== */\r\nconst handlePageSizeChange = (newPageSize: number) => {\r\n pageSize.value = newPageSize;\r\n currentExcelPage.value = 1;\r\n};\r\n\r\nconst syncSheetData = (sheetName: string) => {\r\n const sheet = props.sheets.find((s) => s.name === sheetName);\r\n if (sheet) {\r\n currentData.value = sheet.data;\r\n currentColumns.value = sheet.columns;\r\n currentExcelPage.value = 1;\r\n }\r\n};\r\n\r\n/* ==================== 监听器 ==================== */\r\nwatch(activeSheet, (newSheet) => {\r\n syncSheetData(newSheet);\r\n});\r\n\r\n/* sheets 变化时初始化 */\r\nwatch(\r\n () => props.sheets,\r\n (newSheets) => {\r\n if (newSheets.length > 0) {\r\n const [firstSheet] = newSheets;\r\n activeSheet.value = firstSheet.name;\r\n currentData.value = firstSheet.data;\r\n currentColumns.value = firstSheet.columns;\r\n currentExcelPage.value = 1;\r\n }\r\n },\r\n { immediate: true },\r\n);\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n@use \"./index.scss\";\r\n</style>\r\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","<!--\r\n * @Author: ChenYu ycyplus@gmail.com\r\n * @Date: 2025-07-01\r\n * @Description: 文件预览组件(PDF/Word/Excel)\r\n * @Migration: naive-ui-components 组件库迁移版本\r\n * Copyright (c) 2025 by CHENY, All Rights Reserved.\r\n-->\r\n\r\n<template>\r\n <div class=\"c-file-preview-wrapper\">\r\n <!-- 文件信息卡片模式 -->\r\n <div v-if=\"!autoPreview\" class=\"file-info-card\">\r\n <div class=\"file-info\">\r\n <div class=\"file-icon\">\r\n <C_Icon\r\n :name=\"fileConfig.icon\"\r\n :size=\"40\"\r\n :color=\"fileConfig.color\"\r\n />\r\n </div>\r\n\r\n <div class=\"file-details\">\r\n <div class=\"file-name\">\r\n <NEllipsis style=\"max-width: 250px\">{{\r\n displayFileName\r\n }}</NEllipsis>\r\n <NTag :type=\"fileConfig.tagType\" size=\"small\">\r\n {{ fileType.toUpperCase() }}\r\n </NTag>\r\n </div>\r\n\r\n <div class=\"file-meta\">\r\n <span class=\"file-size\">{{ formatFileSize(fileSize) }}</span>\r\n </div>\r\n </div>\r\n\r\n <div class=\"file-actions\">\r\n <NButton type=\"primary\" @click=\"openPreview\">\r\n <template #icon>\r\n <C_Icon name=\"ic:outline-visibility\" />\r\n </template>\r\n 预览\r\n </NButton>\r\n\r\n <NButton type=\"tertiary\" @click=\"downloadFile\">\r\n <template #icon>\r\n <C_Icon name=\"ic:outline-download\" />\r\n </template>\r\n 下载\r\n </NButton>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- 模态框预览 -->\r\n <NModal\r\n v-model:show=\"showModal\"\r\n :mask-closable=\"false\"\r\n :closable=\"false\"\r\n :auto-focus=\"false\"\r\n transform-origin=\"center\"\r\n style=\"\r\n width: 85vw;\r\n max-width: 1200px;\r\n min-width: 800px;\r\n height: 75vh;\r\n max-height: 700px;\r\n min-height: 500px;\r\n \"\r\n >\r\n <div ref=\"modalContainer\" class=\"modal-container\">\r\n <!-- 自定义头部 -->\r\n <div class=\"modal-header\">\r\n <div class=\"modal-title\">\r\n <C_Icon\r\n :name=\"fileConfig.icon\"\r\n :size=\"20\"\r\n :color=\"fileConfig.color\"\r\n />\r\n <span>{{ displayFileName }}</span>\r\n </div>\r\n <div class=\"modal-actions\">\r\n <NButton size=\"small\" type=\"tertiary\" @click=\"downloadFile\">\r\n <template #icon>\r\n <C_Icon name=\"ic:outline-download\" />\r\n </template>\r\n 下载\r\n </NButton>\r\n <NButton size=\"small\" type=\"tertiary\" @click=\"showModal = false\">\r\n <template #icon>\r\n <C_Icon name=\"ic:outline-close\" />\r\n </template>\r\n </NButton>\r\n </div>\r\n </div>\r\n\r\n <!-- 预览内容 -->\r\n <div class=\"modal-content\">\r\n <!-- 文件信息头部 -->\r\n <div class=\"preview-header\">\r\n <div class=\"flex justify-between items-center\">\r\n <div class=\"flex items-center gap-3\">\r\n <NTag :type=\"fileConfig.tagType\" size=\"small\">\r\n <template #icon>\r\n <C_Icon :name=\"fileConfig.icon\" />\r\n </template>\r\n {{ fileType.toUpperCase() }}\r\n </NTag>\r\n <NEllipsis style=\"max-width: 300px\">{{\r\n displayFileName\r\n }}</NEllipsis>\r\n <span class=\"text-sm text-gray-500\">{{\r\n formatFileSize(fileSize)\r\n }}</span>\r\n </div>\r\n\r\n <div class=\"flex gap-2\">\r\n <NButton\r\n size=\"small\"\r\n type=\"tertiary\"\r\n :disabled=\"loading\"\r\n @click=\"loadFile\"\r\n >\r\n <template #icon>\r\n <C_Icon name=\"ic:outline-refresh\" />\r\n </template>\r\n 刷新\r\n </NButton>\r\n <NButton size=\"small\" type=\"primary\" @click=\"toggleFullscreen\">\r\n <template #icon>\r\n <C_Icon\r\n :name=\"\r\n isFullscreen\r\n ? 'ic:outline-fullscreen-exit'\r\n : 'ic:outline-fullscreen'\r\n \"\r\n />\r\n </template>\r\n {{ isFullscreen ? \"退出全屏\" : \"全屏\" }}\r\n </NButton>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- 预览内容区域 -->\r\n <div class=\"preview-content\">\r\n <!-- 加载和错误状态 -->\r\n <template v-if=\"loading || error\">\r\n <div class=\"status-container\">\r\n <NSpin v-if=\"loading\" size=\"large\">\r\n <template #description>\r\n 正在加载{{ fileType.toUpperCase() }}文件...\r\n </template>\r\n </NSpin>\r\n <NResult\r\n v-else\r\n status=\"error\"\r\n title=\"预览失败\"\r\n :description=\"error\"\r\n >\r\n <template #footer>\r\n <NButton @click=\"loadFile\">重试</NButton>\r\n </template>\r\n </NResult>\r\n </div>\r\n </template>\r\n\r\n <!-- 文件预览 — 委托给子组件 -->\r\n <template v-else>\r\n <PdfViewer\r\n v-if=\"fileType === 'pdf'\"\r\n :pdf-url=\"pdfUrl\"\r\n :total-pages=\"pdfTotalPages\"\r\n />\r\n\r\n <WordViewer\r\n v-else-if=\"fileType === 'word'\"\r\n :content=\"wordContent\"\r\n :headings=\"wordHeadings\"\r\n />\r\n\r\n <ExcelViewer\r\n v-else-if=\"fileType === 'excel'\"\r\n :sheets=\"excelSheets\"\r\n @reload=\"loadFile\"\r\n />\r\n\r\n <!-- 不支持的文件类型 -->\r\n <NResult\r\n v-else\r\n status=\"warning\"\r\n title=\"不支持的文件格式\"\r\n :description=\"`暂不支持预览 ${fileType.toUpperCase()} 格式文件`\"\r\n />\r\n </template>\r\n </div>\r\n </div>\r\n </div>\r\n </NModal>\r\n </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref, toRefs, watch } from \"vue\";\r\nimport { NButton, NEllipsis, NTag, NModal, NSpin, NResult } from \"naive-ui\";\r\nimport { formatFileSize } from \"./data\";\r\nimport PdfViewer from \"./components/PdfViewer/index.vue\";\r\nimport WordViewer from \"./components/WordViewer/index.vue\";\r\nimport ExcelViewer from \"./components/ExcelViewer/index.vue\";\r\nimport { useFilePreview } from \"./composables/useFilePreview\";\r\nimport { useFullscreen } from \"./composables/useFullscreen\";\r\n\r\ndefineOptions({ name: \"C_FilePreview\" });\r\n\r\nconst props = withDefaults(\r\n defineProps<{\r\n file?: File;\r\n url?: string;\r\n fileName?: string;\r\n autoPreview?: boolean;\r\n }>(),\r\n {\r\n fileName: \"未知文件\",\r\n autoPreview: false,\r\n },\r\n);\r\n\r\nconst { file, url, fileName: propFileName, autoPreview } = toRefs(props);\r\n\r\nconst emit = defineEmits<{\r\n preview: [file: File | string];\r\n download: [file: File | string];\r\n}>();\r\n\r\n/* ==================== Composables ==================== */\r\nconst {\r\n loading,\r\n error,\r\n fileSize,\r\n showModal,\r\n pdfUrl,\r\n pdfTotalPages,\r\n wordContent,\r\n wordHeadings,\r\n excelSheets,\r\n displayFileName,\r\n fileType,\r\n fileConfig,\r\n loadFile,\r\n openPreview,\r\n downloadFile,\r\n} = useFilePreview({ file, url, fileName: propFileName }, emit);\r\n\r\nconst modalContainer = ref<HTMLElement>();\r\nconst { isFullscreen, toggleFullscreen, exitFullscreen } =\r\n useFullscreen(modalContainer);\r\n\r\n/* ==================== Modal 关闭时退出全屏 ==================== */\r\nwatch(showModal, (isShow) => {\r\n if (!isShow) exitFullscreen();\r\n});\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n@use \"./index.scss\";\r\n</style>\r\n","<!--\r\n * @Author: ChenYu ycyplus@gmail.com\r\n * @Date: 2025-07-01\r\n * @Description: 文件预览组件(PDF/Word/Excel)\r\n * @Migration: naive-ui-components 组件库迁移版本\r\n * Copyright (c) 2025 by CHENY, All Rights Reserved.\r\n-->\r\n\r\n<template>\r\n <div class=\"c-file-preview-wrapper\">\r\n <!-- 文件信息卡片模式 -->\r\n <div v-if=\"!autoPreview\" class=\"file-info-card\">\r\n <div class=\"file-info\">\r\n <div class=\"file-icon\">\r\n <C_Icon\r\n :name=\"fileConfig.icon\"\r\n :size=\"40\"\r\n :color=\"fileConfig.color\"\r\n />\r\n </div>\r\n\r\n <div class=\"file-details\">\r\n <div class=\"file-name\">\r\n <NEllipsis style=\"max-width: 250px\">{{\r\n displayFileName\r\n }}</NEllipsis>\r\n <NTag :type=\"fileConfig.tagType\" size=\"small\">\r\n {{ fileType.toUpperCase() }}\r\n </NTag>\r\n </div>\r\n\r\n <div class=\"file-meta\">\r\n <span class=\"file-size\">{{ formatFileSize(fileSize) }}</span>\r\n </div>\r\n </div>\r\n\r\n <div class=\"file-actions\">\r\n <NButton type=\"primary\" @click=\"openPreview\">\r\n <template #icon>\r\n <C_Icon name=\"ic:outline-visibility\" />\r\n </template>\r\n 预览\r\n </NButton>\r\n\r\n <NButton type=\"tertiary\" @click=\"downloadFile\">\r\n <template #icon>\r\n <C_Icon name=\"ic:outline-download\" />\r\n </template>\r\n 下载\r\n </NButton>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- 模态框预览 -->\r\n <NModal\r\n v-model:show=\"showModal\"\r\n :mask-closable=\"false\"\r\n :closable=\"false\"\r\n :auto-focus=\"false\"\r\n transform-origin=\"center\"\r\n style=\"\r\n width: 85vw;\r\n max-width: 1200px;\r\n min-width: 800px;\r\n height: 75vh;\r\n max-height: 700px;\r\n min-height: 500px;\r\n \"\r\n >\r\n <div ref=\"modalContainer\" class=\"modal-container\">\r\n <!-- 自定义头部 -->\r\n <div class=\"modal-header\">\r\n <div class=\"modal-title\">\r\n <C_Icon\r\n :name=\"fileConfig.icon\"\r\n :size=\"20\"\r\n :color=\"fileConfig.color\"\r\n />\r\n <span>{{ displayFileName }}</span>\r\n </div>\r\n <div class=\"modal-actions\">\r\n <NButton size=\"small\" type=\"tertiary\" @click=\"downloadFile\">\r\n <template #icon>\r\n <C_Icon name=\"ic:outline-download\" />\r\n </template>\r\n 下载\r\n </NButton>\r\n <NButton size=\"small\" type=\"tertiary\" @click=\"showModal = false\">\r\n <template #icon>\r\n <C_Icon name=\"ic:outline-close\" />\r\n </template>\r\n </NButton>\r\n </div>\r\n </div>\r\n\r\n <!-- 预览内容 -->\r\n <div class=\"modal-content\">\r\n <!-- 文件信息头部 -->\r\n <div class=\"preview-header\">\r\n <div class=\"flex justify-between items-center\">\r\n <div class=\"flex items-center gap-3\">\r\n <NTag :type=\"fileConfig.tagType\" size=\"small\">\r\n <template #icon>\r\n <C_Icon :name=\"fileConfig.icon\" />\r\n </template>\r\n {{ fileType.toUpperCase() }}\r\n </NTag>\r\n <NEllipsis style=\"max-width: 300px\">{{\r\n displayFileName\r\n }}</NEllipsis>\r\n <span class=\"text-sm text-gray-500\">{{\r\n formatFileSize(fileSize)\r\n }}</span>\r\n </div>\r\n\r\n <div class=\"flex gap-2\">\r\n <NButton\r\n size=\"small\"\r\n type=\"tertiary\"\r\n :disabled=\"loading\"\r\n @click=\"loadFile\"\r\n >\r\n <template #icon>\r\n <C_Icon name=\"ic:outline-refresh\" />\r\n </template>\r\n 刷新\r\n </NButton>\r\n <NButton size=\"small\" type=\"primary\" @click=\"toggleFullscreen\">\r\n <template #icon>\r\n <C_Icon\r\n :name=\"\r\n isFullscreen\r\n ? 'ic:outline-fullscreen-exit'\r\n : 'ic:outline-fullscreen'\r\n \"\r\n />\r\n </template>\r\n {{ isFullscreen ? \"退出全屏\" : \"全屏\" }}\r\n </NButton>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- 预览内容区域 -->\r\n <div class=\"preview-content\">\r\n <!-- 加载和错误状态 -->\r\n <template v-if=\"loading || error\">\r\n <div class=\"status-container\">\r\n <NSpin v-if=\"loading\" size=\"large\">\r\n <template #description>\r\n 正在加载{{ fileType.toUpperCase() }}文件...\r\n </template>\r\n </NSpin>\r\n <NResult\r\n v-else\r\n status=\"error\"\r\n title=\"预览失败\"\r\n :description=\"error\"\r\n >\r\n <template #footer>\r\n <NButton @click=\"loadFile\">重试</NButton>\r\n </template>\r\n </NResult>\r\n </div>\r\n </template>\r\n\r\n <!-- 文件预览 — 委托给子组件 -->\r\n <template v-else>\r\n <PdfViewer\r\n v-if=\"fileType === 'pdf'\"\r\n :pdf-url=\"pdfUrl\"\r\n :total-pages=\"pdfTotalPages\"\r\n />\r\n\r\n <WordViewer\r\n v-else-if=\"fileType === 'word'\"\r\n :content=\"wordContent\"\r\n :headings=\"wordHeadings\"\r\n />\r\n\r\n <ExcelViewer\r\n v-else-if=\"fileType === 'excel'\"\r\n :sheets=\"excelSheets\"\r\n @reload=\"loadFile\"\r\n />\r\n\r\n <!-- 不支持的文件类型 -->\r\n <NResult\r\n v-else\r\n status=\"warning\"\r\n title=\"不支持的文件格式\"\r\n :description=\"`暂不支持预览 ${fileType.toUpperCase()} 格式文件`\"\r\n />\r\n </template>\r\n </div>\r\n </div>\r\n </div>\r\n </NModal>\r\n </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref, toRefs, watch } from \"vue\";\r\nimport { NButton, NEllipsis, NTag, NModal, NSpin, NResult } from \"naive-ui\";\r\nimport { formatFileSize } from \"./data\";\r\nimport PdfViewer from \"./components/PdfViewer/index.vue\";\r\nimport WordViewer from \"./components/WordViewer/index.vue\";\r\nimport ExcelViewer from \"./components/ExcelViewer/index.vue\";\r\nimport { useFilePreview } from \"./composables/useFilePreview\";\r\nimport { useFullscreen } from \"./composables/useFullscreen\";\r\n\r\ndefineOptions({ name: \"C_FilePreview\" });\r\n\r\nconst props = withDefaults(\r\n defineProps<{\r\n file?: File;\r\n url?: string;\r\n fileName?: string;\r\n autoPreview?: boolean;\r\n }>(),\r\n {\r\n fileName: \"未知文件\",\r\n autoPreview: false,\r\n },\r\n);\r\n\r\nconst { file, url, fileName: propFileName, autoPreview } = toRefs(props);\r\n\r\nconst emit = defineEmits<{\r\n preview: [file: File | string];\r\n download: [file: File | string];\r\n}>();\r\n\r\n/* ==================== Composables ==================== */\r\nconst {\r\n loading,\r\n error,\r\n fileSize,\r\n showModal,\r\n pdfUrl,\r\n pdfTotalPages,\r\n wordContent,\r\n wordHeadings,\r\n excelSheets,\r\n displayFileName,\r\n fileType,\r\n fileConfig,\r\n loadFile,\r\n openPreview,\r\n downloadFile,\r\n} = useFilePreview({ file, url, fileName: propFileName }, emit);\r\n\r\nconst modalContainer = ref<HTMLElement>();\r\nconst { isFullscreen, toggleFullscreen, exitFullscreen } =\r\n useFullscreen(modalContainer);\r\n\r\n/* ==================== Modal 关闭时退出全屏 ==================== */\r\nwatch(showModal, (isShow) => {\r\n if (!isShow) exitFullscreen();\r\n});\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n@use \"./index.scss\";\r\n</style>\r\n","<!--\r\n * @Author: ChenYu ycyplus@gmail.com\r\n * @Date: 2025-07-01\r\n * @Description: 文件预览组件(PDF/Word/Excel)\r\n * @Migration: naive-ui-components 组件库迁移版本\r\n * Copyright (c) 2025 by CHENY, All Rights Reserved.\r\n-->\r\n\r\n<template>\r\n <div class=\"c-file-preview-wrapper\">\r\n <!-- 文件信息卡片模式 -->\r\n <div v-if=\"!autoPreview\" class=\"file-info-card\">\r\n <div class=\"file-info\">\r\n <div class=\"file-icon\">\r\n <C_Icon\r\n :name=\"fileConfig.icon\"\r\n :size=\"40\"\r\n :color=\"fileConfig.color\"\r\n />\r\n </div>\r\n\r\n <div class=\"file-details\">\r\n <div class=\"file-name\">\r\n <NEllipsis style=\"max-width: 250px\">{{\r\n displayFileName\r\n }}</NEllipsis>\r\n <NTag :type=\"fileConfig.tagType\" size=\"small\">\r\n {{ fileType.toUpperCase() }}\r\n </NTag>\r\n </div>\r\n\r\n <div class=\"file-meta\">\r\n <span class=\"file-size\">{{ formatFileSize(fileSize) }}</span>\r\n </div>\r\n </div>\r\n\r\n <div class=\"file-actions\">\r\n <NButton type=\"primary\" @click=\"openPreview\">\r\n <template #icon>\r\n <C_Icon name=\"ic:outline-visibility\" />\r\n </template>\r\n 预览\r\n </NButton>\r\n\r\n <NButton type=\"tertiary\" @click=\"downloadFile\">\r\n <template #icon>\r\n <C_Icon name=\"ic:outline-download\" />\r\n </template>\r\n 下载\r\n </NButton>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- 模态框预览 -->\r\n <NModal\r\n v-model:show=\"showModal\"\r\n :mask-closable=\"false\"\r\n :closable=\"false\"\r\n :auto-focus=\"false\"\r\n transform-origin=\"center\"\r\n style=\"\r\n width: 85vw;\r\n max-width: 1200px;\r\n min-width: 800px;\r\n height: 75vh;\r\n max-height: 700px;\r\n min-height: 500px;\r\n \"\r\n >\r\n <div ref=\"modalContainer\" class=\"modal-container\">\r\n <!-- 自定义头部 -->\r\n <div class=\"modal-header\">\r\n <div class=\"modal-title\">\r\n <C_Icon\r\n :name=\"fileConfig.icon\"\r\n :size=\"20\"\r\n :color=\"fileConfig.color\"\r\n />\r\n <span>{{ displayFileName }}</span>\r\n </div>\r\n <div class=\"modal-actions\">\r\n <NButton size=\"small\" type=\"tertiary\" @click=\"downloadFile\">\r\n <template #icon>\r\n <C_Icon name=\"ic:outline-download\" />\r\n </template>\r\n 下载\r\n </NButton>\r\n <NButton size=\"small\" type=\"tertiary\" @click=\"showModal = false\">\r\n <template #icon>\r\n <C_Icon name=\"ic:outline-close\" />\r\n </template>\r\n </NButton>\r\n </div>\r\n </div>\r\n\r\n <!-- 预览内容 -->\r\n <div class=\"modal-content\">\r\n <!-- 文件信息头部 -->\r\n <div class=\"preview-header\">\r\n <div class=\"flex justify-between items-center\">\r\n <div class=\"flex items-center gap-3\">\r\n <NTag :type=\"fileConfig.tagType\" size=\"small\">\r\n <template #icon>\r\n <C_Icon :name=\"fileConfig.icon\" />\r\n </template>\r\n {{ fileType.toUpperCase() }}\r\n </NTag>\r\n <NEllipsis style=\"max-width: 300px\">{{\r\n displayFileName\r\n }}</NEllipsis>\r\n <span class=\"text-sm text-gray-500\">{{\r\n formatFileSize(fileSize)\r\n }}</span>\r\n </div>\r\n\r\n <div class=\"flex gap-2\">\r\n <NButton\r\n size=\"small\"\r\n type=\"tertiary\"\r\n :disabled=\"loading\"\r\n @click=\"loadFile\"\r\n >\r\n <template #icon>\r\n <C_Icon name=\"ic:outline-refresh\" />\r\n </template>\r\n 刷新\r\n </NButton>\r\n <NButton size=\"small\" type=\"primary\" @click=\"toggleFullscreen\">\r\n <template #icon>\r\n <C_Icon\r\n :name=\"\r\n isFullscreen\r\n ? 'ic:outline-fullscreen-exit'\r\n : 'ic:outline-fullscreen'\r\n \"\r\n />\r\n </template>\r\n {{ isFullscreen ? \"退出全屏\" : \"全屏\" }}\r\n </NButton>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- 预览内容区域 -->\r\n <div class=\"preview-content\">\r\n <!-- 加载和错误状态 -->\r\n <template v-if=\"loading || error\">\r\n <div class=\"status-container\">\r\n <NSpin v-if=\"loading\" size=\"large\">\r\n <template #description>\r\n 正在加载{{ fileType.toUpperCase() }}文件...\r\n </template>\r\n </NSpin>\r\n <NResult\r\n v-else\r\n status=\"error\"\r\n title=\"预览失败\"\r\n :description=\"error\"\r\n >\r\n <template #footer>\r\n <NButton @click=\"loadFile\">重试</NButton>\r\n </template>\r\n </NResult>\r\n </div>\r\n </template>\r\n\r\n <!-- 文件预览 — 委托给子组件 -->\r\n <template v-else>\r\n <PdfViewer\r\n v-if=\"fileType === 'pdf'\"\r\n :pdf-url=\"pdfUrl\"\r\n :total-pages=\"pdfTotalPages\"\r\n />\r\n\r\n <WordViewer\r\n v-else-if=\"fileType === 'word'\"\r\n :content=\"wordContent\"\r\n :headings=\"wordHeadings\"\r\n />\r\n\r\n <ExcelViewer\r\n v-else-if=\"fileType === 'excel'\"\r\n :sheets=\"excelSheets\"\r\n @reload=\"loadFile\"\r\n />\r\n\r\n <!-- 不支持的文件类型 -->\r\n <NResult\r\n v-else\r\n status=\"warning\"\r\n title=\"不支持的文件格式\"\r\n :description=\"`暂不支持预览 ${fileType.toUpperCase()} 格式文件`\"\r\n />\r\n </template>\r\n </div>\r\n </div>\r\n </div>\r\n </NModal>\r\n </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref, toRefs, watch } from \"vue\";\r\nimport { NButton, NEllipsis, NTag, NModal, NSpin, NResult } from \"naive-ui\";\r\nimport { formatFileSize } from \"./data\";\r\nimport PdfViewer from \"./components/PdfViewer/index.vue\";\r\nimport WordViewer from \"./components/WordViewer/index.vue\";\r\nimport ExcelViewer from \"./components/ExcelViewer/index.vue\";\r\nimport { useFilePreview } from \"./composables/useFilePreview\";\r\nimport { useFullscreen } from \"./composables/useFullscreen\";\r\n\r\ndefineOptions({ name: \"C_FilePreview\" });\r\n\r\nconst props = withDefaults(\r\n defineProps<{\r\n file?: File;\r\n url?: string;\r\n fileName?: string;\r\n autoPreview?: boolean;\r\n }>(),\r\n {\r\n fileName: \"未知文件\",\r\n autoPreview: false,\r\n },\r\n);\r\n\r\nconst { file, url, fileName: propFileName, autoPreview } = toRefs(props);\r\n\r\nconst emit = defineEmits<{\r\n preview: [file: File | string];\r\n download: [file: File | string];\r\n}>();\r\n\r\n/* ==================== Composables ==================== */\r\nconst {\r\n loading,\r\n error,\r\n fileSize,\r\n showModal,\r\n pdfUrl,\r\n pdfTotalPages,\r\n wordContent,\r\n wordHeadings,\r\n excelSheets,\r\n displayFileName,\r\n fileType,\r\n fileConfig,\r\n loadFile,\r\n openPreview,\r\n downloadFile,\r\n} = useFilePreview({ file, url, fileName: propFileName }, emit);\r\n\r\nconst modalContainer = ref<HTMLElement>();\r\nconst { isFullscreen, toggleFullscreen, exitFullscreen } =\r\n useFullscreen(modalContainer);\r\n\r\n/* ==================== Modal 关闭时退出全屏 ==================== */\r\nwatch(showModal, (isShow) => {\r\n if (!isShow) exitFullscreen();\r\n});\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n@use \"./index.scss\";\r\n</style>\r\n"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"C_Form-Jx7PY3sT.css","names":[],"sources":["../src/components/C_Form/layouts/Default/index.vue?vue&type=style&index=0&scoped=3422ba86&lang.css","../src/components/C_Form/layouts/Inline/index.vue?vue&type=style&index=0&scoped=c4648e30&lang.scss","../src/components/C_Form/layouts/Grid/index.vue?vue&type=style&index=0&scoped=ec7e9532&lang.scss","../src/components/C_Form/layouts/Card/index.vue?vue&type=style&index=0&scoped=fff86989&lang.scss","../src/components/C_Form/layouts/Tabs/index.vue?vue&type=style&index=0&scoped=5a6ef2b7&lang.scss","../src/components/C_Form/layouts/Steps/index.vue?vue&type=style&index=0&scoped=c0439a30&lang.scss","../src/components/C_Form/layouts/Dynamic/index.vue?vue&type=style&index=0&scoped=3f0739c2&lang.scss","../src/components/C_Form/layouts/Custom/index.vue?vue&type=style&index=0&scoped=a21051df&lang.scss"],"sourcesContent":["\n.c-form-default[data-v-3422ba86] {\r\n width: 100%;\n}\r\n","/* Inline 布局样式 */\n.c-form-inline[data-v-c4648e30] {\n width: 100%;\n min-height: 0;\n transition: all 0.3s ease;\n}\n.c-form-inline-item[data-v-c4648e30] {\n min-width: 0;\n transition: all 0.3s ease;\n}\n\n/* 确保内部所有表单组件都占满容器宽度 */\n.c-form-inline-item[data-v-c4648e30] .n-form-item {\n width: 100%;\n margin-bottom: 0;\n}\n.c-form-inline-item[data-v-c4648e30] .n-form-item-blank {\n width: 100%;\n}\n.c-form-inline-item[data-v-c4648e30] .n-input,\n.c-form-inline-item[data-v-c4648e30] .n-select,\n.c-form-inline-item[data-v-c4648e30] .n-date-picker,\n.c-form-inline-item[data-v-c4648e30] .n-time-picker,\n.c-form-inline-item[data-v-c4648e30] .n-input-number,\n.c-form-inline-item[data-v-c4648e30] .n-cascader,\n.c-form-inline-item[data-v-c4648e30] .n-color-picker,\n.c-form-inline-item[data-v-c4648e30] .n-auto-complete,\n.c-form-inline-item[data-v-c4648e30] .n-tree-select {\n width: 100% !important;\n}\n\n/* 单选框和复选框组保持自然宽度 */\n.c-form-inline-item[data-v-c4648e30] .n-radio-group,\n.c-form-inline-item[data-v-c4648e30] .n-checkbox-group {\n width: 100%;\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n}\n\n/* 开关组件居左对齐 */\n.c-form-inline-item[data-v-c4648e30] .n-switch {\n width: auto;\n}\n\n/* ================= 对齐方式样式增强 ================= */\n/* 当容器使用 center 对齐时,确保表单项也居中 */\n.c-form-inline[style*=\"justify-content: center\"] .c-form-inline-item[data-v-c4648e30] {\n text-align: center;\n}\n\n/* 当容器使用 end 对齐时,确保表单项也右对齐 */\n.c-form-inline[style*=\"justify-content: flex-end\"] .c-form-inline-item[data-v-c4648e30] {\n text-align: right;\n}\n\n/* 当容器使用 start 对齐时,确保表单项左对齐 */\n.c-form-inline[style*=\"justify-content: flex-start\"] .c-form-inline-item[data-v-c4648e30] {\n text-align: left;\n}\n\n/* ================= 响应式设计 ================= */\n/* 移动设备 - 改为垂直布局 */\n@media (max-width: 768px) {\n.c-form-inline[data-v-c4648e30] {\n flex-direction: column !important;\n gap: 12px !important;\n justify-content: flex-start !important;\n}\n.c-form-inline-item[data-v-c4648e30] {\n width: 100% !important;\n text-align: left !important;\n}\n}\n/* 小屏手机 */\n@media (max-width: 480px) {\n.c-form-inline[data-v-c4648e30] {\n gap: 8px !important;\n}\n}","/* Grid 布局样式 */\n/* 变量定义 */\n.c-grid-layout[data-v-ec7e9532] {\n width: 100%;\n /* 配置面板 */\n /* 网格容器 */\n /* 统计信息 */\n}\n.c-grid-layout .config-panel[data-v-ec7e9532] {\n margin-bottom: 1rem;\n}\n.c-grid-layout .config-panel .config-header[data-v-ec7e9532] {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n font-weight: 500;\n margin-bottom: 8px;\n}\n.c-grid-layout .config-panel .config-controls[data-v-ec7e9532] {\n display: flex;\n gap: 1rem;\n flex-wrap: wrap;\n}\n.c-grid-layout .config-panel .config-controls .config-item[data-v-ec7e9532] {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n}\n.c-grid-layout .config-panel .config-controls .config-item .config-label[data-v-ec7e9532] {\n font-size: 0.875rem;\n white-space: nowrap;\n min-width: 3rem;\n}\n.c-grid-layout .grid-container[data-v-ec7e9532] {\n width: 100%;\n}\n.c-grid-layout .grid-container .grid-item[data-v-ec7e9532] {\n /* 进场动画 */\n animation: fadeInUp-ec7e9532 0.3s ease-out both;\n}\n.c-grid-layout .grid-container .grid-item[data-v-ec7e9532]:nth-child(1) {\n animation-delay: 0.05s;\n}\n.c-grid-layout .grid-container .grid-item[data-v-ec7e9532]:nth-child(2) {\n animation-delay: 0.1s;\n}\n.c-grid-layout .grid-container .grid-item[data-v-ec7e9532]:nth-child(3) {\n animation-delay: 0.15s;\n}\n.c-grid-layout .grid-container .grid-item[data-v-ec7e9532]:nth-child(4) {\n animation-delay: 0.2s;\n}\n.c-grid-layout .grid-container .grid-item[data-v-ec7e9532]:nth-child(5) {\n animation-delay: 0.25s;\n}\n.c-grid-layout .grid-container .grid-item[data-v-ec7e9532]:nth-child(6) {\n animation-delay: 0.3s;\n}\n.c-grid-layout .grid-container .grid-item[data-v-ec7e9532]:nth-child(7) {\n animation-delay: 0.35s;\n}\n.c-grid-layout .grid-container .grid-item[data-v-ec7e9532]:nth-child(8) {\n animation-delay: 0.4s;\n}\n.c-grid-layout .grid-container .grid-item[data-v-ec7e9532]:nth-child(9) {\n animation-delay: 0.45s;\n}\n.c-grid-layout .grid-container .grid-item[data-v-ec7e9532]:nth-child(10) {\n animation-delay: 0.5s;\n}\n.c-grid-layout .grid-container .grid-item[data-v-ec7e9532]:nth-child(11) {\n animation-delay: 0.55s;\n}\n.c-grid-layout .grid-container .grid-item[data-v-ec7e9532]:nth-child(12) {\n animation-delay: 0.6s;\n}\n.c-grid-layout .grid-container .grid-item[data-v-ec7e9532]:nth-child(13) {\n animation-delay: 0.65s;\n}\n.c-grid-layout .grid-container .grid-item[data-v-ec7e9532]:nth-child(14) {\n animation-delay: 0.7s;\n}\n.c-grid-layout .grid-container .grid-item[data-v-ec7e9532]:nth-child(15) {\n animation-delay: 0.75s;\n}\n.c-grid-layout .grid-container .grid-item[data-v-ec7e9532]:nth-child(16) {\n animation-delay: 0.8s;\n}\n.c-grid-layout .grid-container .grid-item[data-v-ec7e9532]:nth-child(17) {\n animation-delay: 0.85s;\n}\n.c-grid-layout .grid-container .grid-item[data-v-ec7e9532]:nth-child(18) {\n animation-delay: 0.9s;\n}\n.c-grid-layout .grid-container .grid-item[data-v-ec7e9532]:nth-child(19) {\n animation-delay: 0.95s;\n}\n.c-grid-layout .grid-container .grid-item[data-v-ec7e9532]:nth-child(20) {\n animation-delay: 1s;\n}\n.c-grid-layout .grid-stats[data-v-ec7e9532] {\n margin-top: 1rem;\n font-size: 0.875rem;\n opacity: 0.8;\n}\n\n/* 动画定义 */\n@keyframes fadeInUp-ec7e9532 {\nfrom {\n opacity: 0;\n transform: translateY(10px) scale(0.95);\n}\nto {\n opacity: 1;\n transform: translateY(0) scale(1);\n}\n}\n/* 表单控件统一宽度 */\n[data-v-ec7e9532] .n-form-item .n-form-item-blank {\n /* 统一所有表单控件的宽度 */\n}\n[data-v-ec7e9532] .n-form-item .n-form-item-blank .n-input,[data-v-ec7e9532] .n-form-item .n-form-item-blank .n-input-number,[data-v-ec7e9532] .n-form-item .n-form-item-blank .n-select,[data-v-ec7e9532] .n-form-item .n-form-item-blank .n-date-picker,[data-v-ec7e9532] .n-form-item .n-form-item-blank .n-time-picker,[data-v-ec7e9532] .n-form-item .n-form-item-blank .n-cascader,[data-v-ec7e9532] .n-form-item .n-form-item-blank .n-tree-select,[data-v-ec7e9532] .n-form-item .n-form-item-blank .n-auto-complete,[data-v-ec7e9532] .n-form-item .n-form-item-blank .n-dynamic-tags {\n width: 100% !important;\n}\n\n/* 响应式设计 */\n@media (max-width: 768px) {\n.c-grid-layout .config-panel .config-controls[data-v-ec7e9532] {\n flex-direction: column;\n gap: 0.75rem;\n}\n.c-grid-layout .config-panel .config-controls .config-item[data-v-ec7e9532] {\n justify-content: space-between;\n}\n.c-grid-layout .grid-container[data-v-ec7e9532] .n-grid {\n gap: 0.5rem !important;\n}\n.c-grid-layout .grid-container .grid-item .item-wrapper[data-v-ec7e9532] {\n padding: 0.125rem;\n}\n.c-grid-layout .grid-stats[data-v-ec7e9532] {\n margin-top: 0.75rem;\n font-size: 0.875rem;\n}\n}\n@media (max-width: 480px) {\n.c-grid-layout .config-panel[data-v-ec7e9532] {\n margin-bottom: 0.75rem;\n}\n}\n/* 主题适配 */\n[data-v-ec7e9532] .n-card {\n --n-border-radius: 8px;\n}\n[data-v-ec7e9532] .n-input-number {\n --n-width: 100%;\n}\n\n/* 暗色主题 */\n@media (prefers-color-scheme: dark) {\n.c-grid-layout .grid-container .grid-item .item-wrapper[data-v-ec7e9532]:hover {\n background-color: rgba(255, 255, 255, 0.05);\n}\n}","/* Card 布局样式 */\n.c-form-card[data-v-fff86989] {\n width: 100%;\n display: flex;\n flex-direction: column;\n gap: 1.5rem;\n}\n\n/* ================= 配置面板 ================= */\n.layout-config-panel[data-v-fff86989] {\n margin-bottom: 0;\n}\n.config-controls[data-v-fff86989] {\n display: flex;\n align-items: center;\n gap: 1.5rem;\n flex-wrap: wrap;\n}\n@media (max-width: 768px) {\n.config-controls[data-v-fff86989] {\n flex-direction: column;\n align-items: stretch;\n gap: 1rem;\n}\n}\n.config-item[data-v-fff86989] {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n font-size: 0.875rem;\n}\n@media (max-width: 768px) {\n.config-item[data-v-fff86989] {\n justify-content: space-between;\n}\n}\n\n/* ================= 表单内容区域 ================= */\n.form-content[data-v-fff86989] {\n display: flex;\n}\n.layout-single[data-v-fff86989],\n.layout-vertical[data-v-fff86989] {\n flex-direction: column;\n}\n.layout-horizontal[data-v-fff86989] {\n flex-direction: row;\n flex-wrap: wrap;\n}\n.layout-horizontal .group-card[data-v-fff86989] {\n flex: 1;\n min-width: 0;\n}\n@media (max-width: 1200px) {\n.layout-horizontal[data-v-fff86989] {\n flex-direction: column;\n}\n}\n\n/* ================= 卡片样式 ================= */\n.single-card[data-v-fff86989],\n.group-card[data-v-fff86989] {\n transition: all 300ms cubic-bezier(0.4, 0, 0.2, 1);\n border-left-width: 4px;\n}\n.single-card[data-v-fff86989],\n.basic-card[data-v-fff86989] {\n border-left-color: #3b82f6;\n}\n.contact-card[data-v-fff86989] {\n border-left-color: #22c55e;\n}\n.preferences-card[data-v-fff86989] {\n border-left-color: #a855f7;\n}\n.group-card.collapsed .card-content[data-v-fff86989] {\n display: none;\n}\n\n/* ================= 卡片头部 ================= */\n.card-header[data-v-fff86989] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n width: 100%;\n}\n.header-info[data-v-fff86989] {\n display: flex;\n align-items: center;\n gap: 1rem;\n}\n.card-icon[data-v-fff86989] {\n width: 2.5rem;\n height: 2.5rem;\n padding: 0.5rem;\n border-radius: 0.5rem;\n background: linear-gradient(to bottom right, #3b82f6, #9333ea);\n color: white;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 1.125rem;\n}\n.header-text h3[data-v-fff86989] {\n font-size: 1.125rem;\n font-weight: 600;\n margin: 0 0 0.25rem;\n}\n.header-text p[data-v-fff86989] {\n font-size: 0.875rem;\n color: #6b7280;\n margin: 0;\n}\n.header-actions[data-v-fff86989] {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n}\n.field-stats[data-v-fff86989] {\n display: flex;\n gap: 0.5rem;\n}\n\n/* ================= 卡片内容 ================= */\n.card-content[data-v-fff86989] {\n padding-top: 1rem;\n}\n.progress-section[data-v-fff86989] {\n padding-bottom: 1rem;\n}\n\n/* ================= 操作面板 ================= */\n.action-content[data-v-fff86989] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 1.5rem;\n}\n@media (max-width: 768px) {\n.action-content[data-v-fff86989] {\n flex-direction: column;\n align-items: stretch;\n gap: 1rem;\n}\n}\n.status-summary[data-v-fff86989] {\n display: flex;\n gap: 1.5rem;\n align-items: center;\n flex-wrap: wrap;\n}\n.status-item[data-v-fff86989] {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n}\n.status-item .label[data-v-fff86989] {\n font-size: 0.875rem;\n}\n.progress-display[data-v-fff86989] {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n min-width: 8rem;\n}\n.action-buttons[data-v-fff86989] {\n display: flex;\n gap: 0.75rem;\n}","/* Tabs 布局样式 */\n.c-form-tabs[data-v-5a6ef2b7] {\n width: 100%;\n}\n.single-panel[data-v-5a6ef2b7] {\n width: 100%;\n}\n.tabs-container[data-v-5a6ef2b7] {\n width: 100%;\n}\n.form-tabs[data-v-5a6ef2b7] {\n width: 100%;\n}\n.tab-icon[data-v-5a6ef2b7] {\n font-size: 16px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n}\n.tab-header[data-v-5a6ef2b7] {\n margin-bottom: 16px;\n padding-bottom: 12px;\n border-bottom: 1px solid var(--n-border-color);\n}\n.tab-description[data-v-5a6ef2b7] {\n margin: 0;\n font-size: 14px;\n line-height: 1.5;\n opacity: 0.8;\n}\n.tab-form-items[data-v-5a6ef2b7] {\n width: 100%;\n}\n.tab-empty[data-v-5a6ef2b7] {\n padding: 40px 0;\n}\n.tabs-actions[data-v-5a6ef2b7] {\n margin-top: 16px;\n padding-top: 12px;\n border-top: 1px solid var(--n-border-color);\n}\n\n/* 响应式设计 */\n@media (max-width: 768px) {\n.tabs-actions[data-v-5a6ef2b7] {\n margin-top: 12px;\n padding-top: 8px;\n}\n.tabs-actions[data-v-5a6ef2b7] .n-space {\n flex-wrap: wrap;\n}\n}","/* Steps 布局样式 */\n.c-form-steps[data-v-c0439a30] {\n display: flex;\n flex-direction: column;\n gap: 24px;\n}\n.single-panel[data-v-c0439a30] {\n width: 100%;\n}\n.steps-container[data-v-c0439a30] {\n display: flex;\n flex-direction: column;\n gap: 24px;\n}\n.steps-indicator[data-v-c0439a30] {\n padding: 24px;\n border-radius: 8px;\n}\n.steps-content[data-v-c0439a30] {\n min-height: 400px;\n}\n.step-panel[data-v-c0439a30] {\n animation: fadeIn-c0439a30 0.3s ease-in-out;\n}\n.step-header[data-v-c0439a30] {\n margin-bottom: 24px;\n padding-bottom: 16px;\n border-bottom: 1px solid var(--n-border-color);\n}\n.step-title[data-v-c0439a30] {\n margin: 0 0 8px 0;\n font-size: 18px;\n font-weight: 600;\n}\n.step-description[data-v-c0439a30] {\n margin: 0;\n font-size: 14px;\n line-height: 1.5;\n}\n.step-form-items[data-v-c0439a30] {\n width: 100%;\n}\n.steps-actions[data-v-c0439a30] {\n margin-top: 24px;\n padding-top: 16px;\n border-top: 1px solid var(--n-border-color);\n}\n@keyframes fadeIn-c0439a30 {\nfrom {\n opacity: 0;\n transform: translateY(8px);\n}\nto {\n opacity: 1;\n transform: translateY(0);\n}\n}\n/* 垂直步骤样式 */\n.steps-container[data-v-c0439a30]:has(.steps-indicator:deep(.n-steps--vertical)) {\n flex-direction: row;\n align-items: flex-start;\n}\n.steps-container:has(.steps-indicator:deep(.n-steps--vertical)) .steps-indicator[data-v-c0439a30] {\n flex-shrink: 0;\n width: 250px;\n margin-right: 24px;\n}\n.steps-container:has(.steps-indicator:deep(.n-steps--vertical)) .steps-content[data-v-c0439a30] {\n flex: 1;\n}\n\n/* 响应式设计 */\n@media (max-width: 768px) {\n.steps-container[data-v-c0439a30]:has(.steps-indicator:deep(.n-steps--vertical)) {\n flex-direction: column !important;\n}\n.steps-container:has(.steps-indicator:deep(.n-steps--vertical)) .steps-indicator[data-v-c0439a30] {\n width: 100% !important;\n margin-right: 0 !important;\n margin-bottom: 16px;\n}\n}\n@media (prefers-reduced-motion: reduce) {\n.step-panel[data-v-c0439a30] {\n animation: none !important;\n}\n}","/* Dynamic 布局样式 */\n.c-form-dynamic[data-v-3f0739c2] {\n width: 100%;\n}\n.dynamic-controls[data-v-3f0739c2],\n.dynamic-controls-fallback[data-v-3f0739c2] {\n margin-bottom: 16px;\n}\n.dynamic-stats[data-v-3f0739c2] {\n margin-top: 16px;\n padding-top: 12px;\n border-top: 1px solid var(--n-divider-color);\n}\n.dynamic-item-wrapper[data-v-3f0739c2] {\n position: relative;\n transition: all 0.3s ease;\n animation: fadeInUp-3f0739c2 0.3s ease-out;\n}\n.dynamic-item-wrapper.is-dynamic-field[data-v-3f0739c2] {\n border: 1px dashed var(--n-color-primary);\n border-radius: 6px;\n padding: 8px;\n background-color: var(--n-color-primary-suppl);\n}\n.max-fields-config[data-v-3f0739c2] {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 14px;\n}\n.max-fields-config span[data-v-3f0739c2] {\n font-weight: 500;\n white-space: nowrap;\n color: var(--n-text-color-2);\n}\n@keyframes fadeInUp-3f0739c2 {\nfrom {\n opacity: 0;\n transform: translateY(10px);\n}\nto {\n opacity: 1;\n transform: translateY(0);\n}\n}\n/* 响应式设计 */\n@media (max-width: 768px) {\n.dynamic-controls[data-v-3f0739c2],\n .dynamic-controls-fallback[data-v-3f0739c2] {\n margin-bottom: 12px;\n}\n.dynamic-stats[data-v-3f0739c2] {\n margin-top: 12px;\n}\n.dynamic-item-wrapper.is-dynamic-field[data-v-3f0739c2] {\n padding: 6px;\n}\n.max-fields-config[data-v-3f0739c2] {\n margin-top: 8px;\n}\n}\n/* 辅助功能 */\n@media (prefers-reduced-motion: reduce) {\n.dynamic-item-wrapper[data-v-3f0739c2] {\n animation: none !important;\n transition: none !important;\n}\n}\n@media (prefers-contrast: high) {\n.dynamic-item-wrapper.is-dynamic-field[data-v-3f0739c2] {\n border-width: 2px;\n border-color: currentColor;\n}\n}","/* Custom 布局样式 */\n.custom-layout .toolbar-card[data-v-a21051df] {\n margin-bottom: 16px;\n}\n.custom-layout .toolbar-card .toolbar-content[data-v-a21051df] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n flex-wrap: wrap;\n gap: 16px;\n}\n.custom-layout .toolbar-card .toolbar-content .mode-section[data-v-a21051df],\n.custom-layout .toolbar-card .toolbar-content .stats-section[data-v-a21051df],\n.custom-layout .toolbar-card .toolbar-content .actions-section[data-v-a21051df] {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n.custom-layout .toolbar-card .toolbar-content .section-label[data-v-a21051df] {\n font-size: 14px;\n font-weight: 500;\n}\n.custom-layout .toolbar-card .toolbar-content .stat-item[data-v-a21051df] {\n text-align: center;\n min-width: 60px;\n}\n.custom-layout .toolbar-card .toolbar-content .stat-item .stat-value[data-v-a21051df] {\n display: block;\n font-size: 18px;\n font-weight: 600;\n color: var(--n-primary-color);\n}\n.custom-layout .toolbar-card .toolbar-content .stat-item .stat-label[data-v-a21051df] {\n font-size: 12px;\n opacity: 0.7;\n margin-top: 4px;\n}\n.custom-layout .design-panel[data-v-a21051df] {\n margin-bottom: 16px;\n}\n.custom-layout .design-panel .design-tools[data-v-a21051df] {\n display: flex;\n gap: 24px;\n flex-wrap: wrap;\n}\n.custom-layout .design-panel .design-tools .tool-group[data-v-a21051df] {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n.custom-layout .design-panel .design-tools .tool-group .group-label[data-v-a21051df] {\n font-size: 14px;\n font-weight: 500;\n margin-right: 4px;\n}\n.custom-layout .layout-canvas[data-v-a21051df] {\n min-height: 200px;\n}\n.custom-layout .layout-canvas.design-mode[data-v-a21051df] {\n border: 2px dashed var(--n-border-color);\n border-radius: 8px;\n padding: 16px;\n background: var(--n-body-color);\n}\n.custom-layout .layout-canvas .canvas-hint[data-v-a21051df] {\n display: flex;\n align-items: center;\n justify-content: center;\n height: 120px;\n text-align: center;\n}\n.custom-layout .layout-canvas .canvas-hint .hint-content h3[data-v-a21051df] {\n margin: 0 0 8px 0;\n font-size: 18px;\n}\n.custom-layout .layout-canvas .canvas-hint .hint-content p[data-v-a21051df] {\n margin: 0;\n opacity: 0.7;\n font-size: 14px;\n}\n.custom-layout .layout-canvas .areas-container[data-v-a21051df] {\n display: flex;\n flex-wrap: wrap;\n gap: 16px;\n}\n.custom-layout .layout-canvas .custom-area[data-v-a21051df] {\n border: 1px solid var(--n-border-color);\n border-radius: 8px;\n background: var(--n-card-color);\n padding: 16px;\n min-height: 120px;\n flex: 1;\n min-width: 250px;\n}\n.custom-layout .layout-canvas .custom-area .area-header[data-v-a21051df] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 16px;\n padding-bottom: 8px;\n border-bottom: 1px solid var(--n-divider-color);\n}\n.custom-layout .layout-canvas .custom-area .area-header .area-info[data-v-a21051df] {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n.custom-layout .layout-canvas .custom-area .area-header .area-info .area-title[data-v-a21051df] {\n font-weight: 600;\n font-size: 14px;\n cursor: pointer;\n padding: 2px 6px;\n border-radius: 4px;\n transition: all 0.2s ease;\n}\n.custom-layout .layout-canvas .custom-area .area-header .area-info .area-title[data-v-a21051df]:hover {\n background: var(--n-button-color-hover);\n color: var(--n-primary-color);\n}\n.custom-layout .layout-canvas .custom-area .area-header .area-info .title-input[data-v-a21051df] {\n min-width: 120px;\n max-width: 200px;\n}\n.custom-layout .layout-canvas .custom-area .area-header .area-controls[data-v-a21051df] {\n display: flex;\n gap: 4px;\n}\n.custom-layout .layout-canvas .custom-area .area-fields[data-v-a21051df] {\n display: flex;\n flex-direction: column;\n gap: 8px;\n min-height: 60px;\n}\n.custom-layout .layout-canvas .custom-area .area-drop-zone[data-v-a21051df] {\n display: flex;\n align-items: center;\n justify-content: center;\n height: 60px;\n border: 2px dashed var(--n-border-color);\n border-radius: 6px;\n font-size: 14px;\n opacity: 0.6;\n transition: all 0.2s ease;\n background: var(--n-body-color);\n margin-top: 8px;\n}\n.custom-layout .layout-canvas .custom-area .area-drop-zone[data-v-a21051df]:hover {\n border-color: var(--n-primary-color);\n opacity: 1;\n}\n.custom-layout .layout-canvas .custom-area.area-horizontal .area-fields[data-v-a21051df] {\n flex-direction: row;\n flex-wrap: wrap;\n gap: 12px;\n}\n.custom-layout .layout-canvas .custom-area.area-grid .area-fields[data-v-a21051df] {\n display: grid;\n grid-template-columns: repeat(2, 1fr);\n gap: 8px;\n}\n.custom-layout .layout-canvas .field-item[data-v-a21051df] {\n border: 1px solid var(--n-border-color);\n border-radius: 6px;\n background: var(--n-body-color);\n padding: 12px;\n min-height: 40px;\n cursor: move;\n transition: all 0.2s ease;\n}\n.custom-layout .layout-canvas .field-item[data-v-a21051df]:hover {\n border-color: var(--n-primary-color);\n transform: translateY(-1px);\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\n}\n.custom-layout .layout-canvas .field-item .field-preview[data-v-a21051df] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n gap: 8px;\n}\n.custom-layout .layout-canvas .field-item .field-preview .field-label[data-v-a21051df] {\n font-size: 13px;\n font-weight: 500;\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.custom-layout .layout-canvas .field-item .field-preview .field-type[data-v-a21051df] {\n font-size: 11px;\n opacity: 0.6;\n background: var(--n-tag-color);\n padding: 2px 6px;\n border-radius: 4px;\n flex-shrink: 0;\n}\n.custom-layout .layout-canvas .field-pool[data-v-a21051df] {\n margin-top: 16px;\n}\n.custom-layout .layout-canvas .field-pool .pool-fields-grid[data-v-a21051df] {\n display: grid;\n grid-template-columns: repeat(4, 1fr);\n gap: 12px;\n}\n.custom-layout .layout-canvas .field-pool .pool-field[data-v-a21051df] {\n border: 1px solid var(--n-border-color);\n border-radius: 6px;\n background: var(--n-card-color);\n padding: 12px;\n min-height: 40px;\n cursor: move;\n transition: all 0.2s ease;\n display: flex;\n justify-content: space-between;\n align-items: center;\n}\n.custom-layout .layout-canvas .field-pool .pool-field[data-v-a21051df]:hover {\n border-color: var(--n-primary-color);\n transform: translateY(-1px);\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\n}\n.custom-layout .layout-canvas .field-pool .pool-field .field-name[data-v-a21051df] {\n font-size: 13px;\n font-weight: 500;\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.custom-layout .layout-canvas .field-pool .pool-field .field-type-tag[data-v-a21051df] {\n font-size: 11px;\n padding: 2px 8px;\n border-radius: 4px;\n background: var(--n-tag-color);\n flex-shrink: 0;\n}\n.custom-layout .layout-canvas .empty-layout[data-v-a21051df] {\n display: flex;\n align-items: center;\n justify-content: center;\n height: 120px;\n padding: 16px;\n}\n.custom-layout .layout-canvas .form-areas[data-v-a21051df] {\n display: flex;\n flex-wrap: wrap;\n gap: 16px;\n align-items: flex-start;\n}\n.custom-layout .layout-canvas .form-areas .form-area[data-v-a21051df] {\n flex: 1;\n min-width: 250px;\n}\n.custom-layout .layout-canvas .form-areas .form-area.area-vertical[data-v-a21051df] {\n width: 100%;\n}\n.custom-layout .layout-canvas .form-areas .form-area .area-form-items[data-v-a21051df] {\n display: flex;\n flex-direction: column;\n gap: 16px;\n /* 统一表单项宽度 */\n}\n.custom-layout .layout-canvas .form-areas .form-area .area-form-items[data-v-a21051df] .n-form-item {\n width: 100%;\n}\n.custom-layout .layout-canvas .form-areas .form-area .area-form-items[data-v-a21051df] .n-form-item .n-form-item-blank {\n width: 100%;\n /* 统一输入控件宽度 */\n /* 特殊控件的额外处理 */\n}\n.custom-layout .layout-canvas .form-areas .form-area .area-form-items[data-v-a21051df] .n-form-item .n-form-item-blank .n-input,\n.custom-layout .layout-canvas .form-areas .form-area .area-form-items[data-v-a21051df] .n-form-item .n-form-item-blank .n-select,\n.custom-layout .layout-canvas .form-areas .form-area .area-form-items[data-v-a21051df] .n-form-item .n-form-item-blank .n-date-picker,\n.custom-layout .layout-canvas .form-areas .form-area .area-form-items[data-v-a21051df] .n-form-item .n-form-item-blank .n-input-number,\n.custom-layout .layout-canvas .form-areas .form-area .area-form-items[data-v-a21051df] .n-form-item .n-form-item-blank .n-textarea,\n.custom-layout .layout-canvas .form-areas .form-area .area-form-items[data-v-a21051df] .n-form-item .n-form-item-blank .n-radio-group,\n.custom-layout .layout-canvas .form-areas .form-area .area-form-items[data-v-a21051df] .n-form-item .n-form-item-blank .n-checkbox-group,\n.custom-layout .layout-canvas .form-areas .form-area .area-form-items[data-v-a21051df] .n-form-item .n-form-item-blank .n-cascader,\n.custom-layout .layout-canvas .form-areas .form-area .area-form-items[data-v-a21051df] .n-form-item .n-form-item-blank .n-tree-select,\n.custom-layout .layout-canvas .form-areas .form-area .area-form-items[data-v-a21051df] .n-form-item .n-form-item-blank .n-time-picker,\n.custom-layout .layout-canvas .form-areas .form-area .area-form-items[data-v-a21051df] .n-form-item .n-form-item-blank .n-color-picker {\n width: 100% !important;\n max-width: 100% !important;\n}\n.custom-layout .layout-canvas .form-areas .form-area .area-form-items[data-v-a21051df] .n-form-item .n-form-item-blank .n-radio-group,\n.custom-layout .layout-canvas .form-areas .form-area .area-form-items[data-v-a21051df] .n-form-item .n-form-item-blank .n-checkbox-group {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n}\n.custom-layout .layout-canvas .form-areas .form-area .area-form-items.layout-horizontal[data-v-a21051df] {\n flex-direction: row;\n flex-wrap: wrap;\n gap: 12px;\n}\n.custom-layout .layout-canvas .form-areas .form-area .area-form-items.layout-horizontal[data-v-a21051df] .n-form-item {\n flex: 1;\n min-width: 200px;\n}\n.custom-layout .layout-canvas .form-areas .form-area .area-form-items.layout-grid[data-v-a21051df] {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));\n gap: 16px;\n}\n.custom-layout .layout-canvas .form-areas .form-area .area-form-items.layout-grid[data-v-a21051df] .n-form-item {\n width: 100%;\n}\n\n/* 拖拽状态 */\n.area-ghost[data-v-a21051df],\n.field-ghost[data-v-a21051df] {\n opacity: 0.5;\n background: var(--n-primary-color-suppl);\n border: 2px dashed var(--n-primary-color);\n transform: rotate(2deg);\n}\n\n/* 响应式 */\n@media (max-width: 1024px) {\n.custom-layout .toolbar-content[data-v-a21051df] {\n flex-direction: column;\n gap: 12px;\n}\n.custom-layout .layout-canvas .areas-container[data-v-a21051df] {\n flex-direction: column;\n}\n}\n@media (max-width: 768px) {\n.custom-layout .design-tools[data-v-a21051df] {\n flex-direction: column;\n gap: 12px;\n}\n.custom-layout .layout-canvas.design-mode[data-v-a21051df] {\n padding: 12px;\n}\n.custom-layout .custom-area[data-v-a21051df] {\n padding: 12px;\n min-height: 100px;\n}\n.custom-layout .layout-canvas .field-pool .pool-fields-grid[data-v-a21051df] {\n grid-template-columns: repeat(2, 1fr);\n}\n}"],"mappings":";AACA;AACA;AACA;;ACHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AC/EA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;ACnKA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;ACxKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;ACnDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;ACtFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;ACzEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA"}
|
package/dist/C_Form.cjs
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
require('./C_Icon.js');
|
|
3
|
+
const require_C_Form = require('./C_Form.js');
|
|
4
|
+
|
|
5
|
+
exports.C_Form = require_C_Form.C_Form_default;
|
|
6
|
+
exports.DYNAMIC_FORM_STATE_KEY = require_C_Form.DYNAMIC_FORM_STATE_KEY;
|
|
7
|
+
exports.FIELD_TYPE_OPTIONS = require_C_Form.FIELD_TYPE_OPTIONS;
|
|
8
|
+
exports.FORM_DEFAULTS = require_C_Form.FORM_DEFAULTS;
|
|
9
|
+
exports.LAYOUTS_WITH_OWN_CONTROLS = require_C_Form.LAYOUTS_WITH_OWN_CONTROLS;
|
|
10
|
+
exports.registerRenderer = require_C_Form.registerRenderer;
|
|
11
|
+
exports.resolveFormConfig = require_C_Form.resolveFormConfig;
|
|
12
|
+
exports.shouldShowActions = require_C_Form.shouldShowActions;
|
|
13
|
+
exports.useDynamicFormState = require_C_Form.useDynamicFormState;
|
|
14
|
+
exports.useFormRenderer = require_C_Form.useFormRenderer;
|
|
15
|
+
exports.useFormState = require_C_Form.useFormState;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { A as StepsLayoutConfig, C as FormInstance, D as InlineLayoutConfig, E as GridLayoutConfig, M as TabsLayoutConfig, O as LayoutConfig, S as DynamicFormState, T as FormOption, _ as shouldShowActions, a as ComponentMap, b as CustomLayoutConfig, c as useFormRenderer, d as FORM_DEFAULTS, f as FormConfig, g as resolveFormConfig, h as ResolvedFormConfig, i as useDynamicFormState, j as SubmitEventPayload, k as LayoutType, l as useFormState, m as LayoutCallbacks, n as DynamicFormStateType, o as FormRenderer, p as LAYOUTS_WITH_OWN_CONTROLS, r as FIELD_TYPE_OPTIONS, s as registerRenderer, t as DYNAMIC_FORM_STATE_KEY, u as _default, v as CardLayoutConfig, w as FormModel, x as DynamicFormConfig, y as ComponentType } from "./useDynamicFormState.js";
|
|
2
|
+
export { _default as C_Form, type CardLayoutConfig, type ComponentMap, type ComponentType, type CustomLayoutConfig, DYNAMIC_FORM_STATE_KEY, type DynamicFormConfig, type DynamicFormState, type DynamicFormStateType, FIELD_TYPE_OPTIONS, FORM_DEFAULTS, type FormConfig, type FormInstance, type FormModel, type FormOption, type FormRenderer, type GridLayoutConfig, type InlineLayoutConfig, LAYOUTS_WITH_OWN_CONTROLS, type LayoutCallbacks, type LayoutConfig, type LayoutType, type ResolvedFormConfig, type StepsLayoutConfig, type SubmitEventPayload, type TabsLayoutConfig, registerRenderer, resolveFormConfig, shouldShowActions, useDynamicFormState, useFormRenderer, useFormState };
|
package/dist/C_Form.d.ts
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { A as StepsLayoutConfig, C as FormInstance, D as InlineLayoutConfig, E as GridLayoutConfig, M as TabsLayoutConfig, O as LayoutConfig, S as DynamicFormState, T as FormOption, _ as shouldShowActions, a as ComponentMap, b as CustomLayoutConfig, c as useFormRenderer, d as FORM_DEFAULTS, f as FormConfig, g as resolveFormConfig, h as ResolvedFormConfig, i as useDynamicFormState, j as SubmitEventPayload, k as LayoutType, l as useFormState, m as LayoutCallbacks, n as DynamicFormStateType, o as FormRenderer, p as LAYOUTS_WITH_OWN_CONTROLS, r as FIELD_TYPE_OPTIONS, s as registerRenderer, t as DYNAMIC_FORM_STATE_KEY, u as _default, v as CardLayoutConfig, w as FormModel, x as DynamicFormConfig, y as ComponentType } from "./useDynamicFormState.js";
|
|
2
|
+
export { _default as C_Form, type CardLayoutConfig, type ComponentMap, type ComponentType, type CustomLayoutConfig, DYNAMIC_FORM_STATE_KEY, type DynamicFormConfig, type DynamicFormState, type DynamicFormStateType, FIELD_TYPE_OPTIONS, FORM_DEFAULTS, type FormConfig, type FormInstance, type FormModel, type FormOption, type FormRenderer, type GridLayoutConfig, type InlineLayoutConfig, LAYOUTS_WITH_OWN_CONTROLS, type LayoutCallbacks, type LayoutConfig, type LayoutType, type ResolvedFormConfig, type StepsLayoutConfig, type SubmitEventPayload, type TabsLayoutConfig, registerRenderer, resolveFormConfig, shouldShowActions, useDynamicFormState, useFormRenderer, useFormState };
|
package/dist/C_Form.js
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import "./C_Icon2.js";
|
|
2
|
+
import { a as registerRenderer, c as FORM_DEFAULTS, d as shouldShowActions, i as useDynamicFormState, l as LAYOUTS_WITH_OWN_CONTROLS, n as DYNAMIC_FORM_STATE_KEY, o as useFormRenderer, r as FIELD_TYPE_OPTIONS, s as useFormState, t as C_Form_default, u as resolveFormConfig } from "./C_Form2.js";
|
|
3
|
+
|
|
4
|
+
export { C_Form_default as C_Form, DYNAMIC_FORM_STATE_KEY, FIELD_TYPE_OPTIONS, FORM_DEFAULTS, LAYOUTS_WITH_OWN_CONTROLS, registerRenderer, resolveFormConfig, shouldShowActions, useDynamicFormState, useFormRenderer, useFormState };
|