@robot-admin/naive-ui-components 0.8.1 → 0.9.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.
Files changed (381) hide show
  1. package/README.md +294 -279
  2. package/dist/C_ActionBar-DYG0Yf3A.css.map +1 -0
  3. package/dist/C_ActionBar-MAjRhqcI.css.map +1 -0
  4. package/dist/C_ActionBar.cjs +1 -1
  5. package/dist/C_ActionBar.css +47 -47
  6. package/dist/C_ActionBar.js +1 -1
  7. package/dist/C_ActionBar.js.map +1 -1
  8. package/dist/C_ActionBar2.js +1 -1
  9. package/dist/C_ActionBar2.js.map +1 -1
  10. package/dist/{C_AntV-A3NXx_sF.css.map → C_AntV-BY8jqqmi.css.map} +1 -1
  11. package/dist/{C_AntV-D2Zp2qQF.css.map → C_AntV-BbkHc-_a.css.map} +1 -1
  12. package/dist/C_AntV.cjs +1 -1
  13. package/dist/C_AntV.css +78 -78
  14. package/dist/C_AntV.js +1 -1
  15. package/dist/C_AntV.js.map +1 -1
  16. package/dist/C_AntV2.js +3 -3
  17. package/dist/C_AntV2.js.map +1 -1
  18. package/dist/{C_AudioPlayer-CXl4yP_m.css.map → C_AudioPlayer-DKRIGhi7.css.map} +1 -1
  19. package/dist/{C_AudioPlayer-CcBtt71m.css.map → C_AudioPlayer-DlB6eNsa.css.map} +1 -1
  20. package/dist/C_AudioPlayer.cjs +1 -1
  21. package/dist/C_AudioPlayer.css +47 -47
  22. package/dist/C_AudioPlayer.js +1 -1
  23. package/dist/C_AudioPlayer.js.map +1 -1
  24. package/dist/C_AudioPlayer2.js +1 -1
  25. package/dist/C_AudioPlayer2.js.map +1 -1
  26. package/dist/{C_AvatarGroup-CtPhfH9h.css.map → C_AvatarGroup-D02zci-i.css.map} +1 -1
  27. package/dist/{C_AvatarGroup-M1dNPH3E.css.map → C_AvatarGroup-DatHaUlY.css.map} +1 -1
  28. package/dist/C_AvatarGroup.css +21 -21
  29. package/dist/C_AvatarGroup.js.map +1 -1
  30. package/dist/C_AvatarGroup2.js +1 -1
  31. package/dist/C_AvatarGroup2.js.map +1 -1
  32. package/dist/{C_Barcode-DjTmDkbQ.css.map → C_Barcode-DYDRDe2O.css.map} +1 -1
  33. package/dist/{C_Barcode-Do1Ozsmh.css.map → C_Barcode-muJdc_O4.css.map} +1 -1
  34. package/dist/C_Barcode.css +7 -7
  35. package/dist/C_Barcode.js.map +1 -1
  36. package/dist/C_Barcode2.js +1 -1
  37. package/dist/C_Barcode2.js.map +1 -1
  38. package/dist/C_Breadcrumb.cjs +1 -1
  39. package/dist/C_Breadcrumb.js +1 -1
  40. package/dist/C_Breadcrumb.js.map +1 -1
  41. package/dist/C_Breadcrumb2.js +1 -1
  42. package/dist/C_Breadcrumb2.js.map +1 -1
  43. package/dist/{C_Captcha-CZmAETly.css.map → C_Captcha-9_hk6VmY.css.map} +1 -1
  44. package/dist/{C_Captcha-Ccq3DMrR.css.map → C_Captcha-MtASlJ0f.css.map} +1 -1
  45. package/dist/C_Captcha.css +19 -19
  46. package/dist/C_Captcha.js.map +1 -1
  47. package/dist/C_Captcha2.js +1 -1
  48. package/dist/C_Captcha2.js.map +1 -1
  49. package/dist/C_Cascade.js.map +1 -1
  50. package/dist/C_Cascade2.js +1 -1
  51. package/dist/C_Cascade2.js.map +1 -1
  52. package/dist/{C_Chat-CJ8KESTM.css.map → C_Chat-Csjz_BFw.css.map} +1 -1
  53. package/dist/{C_Chat-DzV4AFLd.css.map → C_Chat-DO1ZBA_0.css.map} +1 -1
  54. package/dist/C_Chat.cjs +1 -1
  55. package/dist/C_Chat.css +65 -65
  56. package/dist/C_Chat.js +1 -1
  57. package/dist/C_Chat.js.map +1 -1
  58. package/dist/C_Chat2.js +1 -1
  59. package/dist/C_Chat2.js.map +1 -1
  60. package/dist/{C_City-Cv5BESaN.css.map → C_City-Bam08Qv3.css.map} +1 -1
  61. package/dist/{C_City-DNKv4MpH.css.map → C_City-Bb3W-KaN.css.map} +1 -1
  62. package/dist/C_City.css +29 -29
  63. package/dist/C_City.js.map +1 -1
  64. package/dist/C_City2.js +1 -1
  65. package/dist/C_City2.js.map +1 -1
  66. package/dist/C_Code-BFi5xxnM.css.map +1 -0
  67. package/dist/C_Code-CZ7yfnri.css.map +1 -0
  68. package/dist/C_Code.cjs +1 -1
  69. package/dist/C_Code.css +3 -3
  70. package/dist/C_Code.js +1 -1
  71. package/dist/C_Code.js.map +1 -1
  72. package/dist/C_Code2.js +1 -1
  73. package/dist/C_Code2.js.map +1 -1
  74. package/dist/{C_CollapsePanel-CedsEM0N.css.map → C_CollapsePanel-CWkFCqNQ.css.map} +1 -1
  75. package/dist/{C_CollapsePanel-BkOivqn3.css.map → C_CollapsePanel-pcVJA_4z.css.map} +1 -1
  76. package/dist/C_CollapsePanel.cjs +1 -1
  77. package/dist/C_CollapsePanel.css +35 -35
  78. package/dist/C_CollapsePanel.js +1 -1
  79. package/dist/C_CollapsePanel.js.map +1 -1
  80. package/dist/C_CollapsePanel2.js +1 -1
  81. package/dist/C_CollapsePanel2.js.map +1 -1
  82. package/dist/{C_ContextMenu-CCsCeI39.css.map → C_ContextMenu-B3Cgz_wJ.css.map} +1 -1
  83. package/dist/{C_ContextMenu-DOTBeltf.css.map → C_ContextMenu-u1LixF3_.css.map} +1 -1
  84. package/dist/C_ContextMenu.cjs +1 -1
  85. package/dist/C_ContextMenu.css +17 -17
  86. package/dist/C_ContextMenu.js +1 -1
  87. package/dist/C_ContextMenu.js.map +1 -1
  88. package/dist/C_ContextMenu2.js +1 -1
  89. package/dist/C_ContextMenu2.js.map +1 -1
  90. package/dist/{C_Cron-C0-8b5af.css.map → C_Cron-Civir5-I.css.map} +1 -1
  91. package/dist/{C_Cron-DqHQ92LN.css.map → C_Cron-iw3qpMsy.css.map} +1 -1
  92. package/dist/C_Cron.cjs +1 -1
  93. package/dist/C_Cron.css +37 -37
  94. package/dist/C_Cron.js +1 -1
  95. package/dist/C_Cron.js.map +1 -1
  96. package/dist/C_Cron2.js +1 -1
  97. package/dist/C_Cron2.js.map +1 -1
  98. package/dist/C_Date.js.map +1 -1
  99. package/dist/C_Date2.js +1 -1
  100. package/dist/C_Date2.js.map +1 -1
  101. package/dist/{C_Draggable-Bq6o0qXn.css.map → C_Draggable-BCjIvIwT.css.map} +1 -1
  102. package/dist/{C_Draggable-r6nhx3yM.css.map → C_Draggable-DwkSlCOS.css.map} +1 -1
  103. package/dist/C_Draggable.css +46 -46
  104. package/dist/C_Draggable.js.map +1 -1
  105. package/dist/C_Draggable2.js +1 -1
  106. package/dist/C_Draggable2.js.map +1 -1
  107. package/dist/C_Editor-BfjjYQ9B.css.map +1 -0
  108. package/dist/C_Editor-Do2StvoJ.css.map +1 -0
  109. package/dist/C_Editor.css +55 -55
  110. package/dist/C_Editor.js.map +1 -1
  111. package/dist/C_Editor2.js +1 -1
  112. package/dist/C_Editor2.js.map +1 -1
  113. package/dist/{C_FilePreview-BVarVvnD.css.map → C_FilePreview-BhcbiXsV.css.map} +1 -1
  114. package/dist/{C_FilePreview-DHGlV4OR.css.map → C_FilePreview-DJudcIbW.css.map} +1 -1
  115. package/dist/C_FilePreview.cjs +1 -1
  116. package/dist/C_FilePreview.css +91 -91
  117. package/dist/C_FilePreview.js +1 -1
  118. package/dist/C_FilePreview.js.map +1 -1
  119. package/dist/C_FilePreview2.js +1 -1
  120. package/dist/C_FilePreview2.js.map +1 -1
  121. package/dist/{C_Form-BciQUPpS.css.map → C_Form-BtcAPIRi.css.map} +1 -1
  122. package/dist/{C_Form-CKHvXL3O.css.map → C_Form-D_gwQ7hC.css.map} +1 -1
  123. package/dist/C_Form.cjs +1 -1
  124. package/dist/C_Form.css +222 -222
  125. package/dist/C_Form.js +1 -1
  126. package/dist/C_Form.js.map +1 -1
  127. package/dist/C_Form2.js +1 -1
  128. package/dist/C_Form2.js.map +1 -1
  129. package/dist/{C_FormSearch-Bmd2CmG6.css.map → C_FormSearch-Bi4XYjjk.css.map} +1 -1
  130. package/dist/{C_FormSearch-DBNtnjaL.css.map → C_FormSearch-DUGOoX0u.css.map} +1 -1
  131. package/dist/C_FormSearch.css +45 -45
  132. package/dist/C_FormSearch.js.map +1 -1
  133. package/dist/C_FormSearch2.js +1 -1
  134. package/dist/C_FormSearch2.js.map +1 -1
  135. package/dist/{C_FormulaEditor-3WG2vtQl.css.map → C_FormulaEditor-CJk3SSUJ.css.map} +1 -1
  136. package/dist/{C_FormulaEditor-Cm0CokN5.css.map → C_FormulaEditor-Cy7mjfVO.css.map} +1 -1
  137. package/dist/C_FormulaEditor.cjs +1 -1
  138. package/dist/C_FormulaEditor.css +78 -78
  139. package/dist/C_FormulaEditor.js +1 -1
  140. package/dist/C_FormulaEditor.js.map +1 -1
  141. package/dist/C_FormulaEditor2.js +1 -1
  142. package/dist/C_FormulaEditor2.js.map +1 -1
  143. package/dist/C_FullCalendar-BQA0OjGB.css.map +1 -0
  144. package/dist/C_FullCalendar-ChJUosAi.css.map +1 -0
  145. package/dist/C_FullCalendar.css +3 -3
  146. package/dist/C_FullCalendar.js.map +1 -1
  147. package/dist/C_FullCalendar2.js +1 -1
  148. package/dist/C_FullCalendar2.js.map +1 -1
  149. package/dist/C_GlobalSearch.js.map +1 -1
  150. package/dist/C_GlobalSearch2.js.map +1 -1
  151. package/dist/C_Guide.cjs +1 -1
  152. package/dist/C_Guide.js +1 -1
  153. package/dist/C_Guide.js.map +1 -1
  154. package/dist/C_Guide2.js +1 -1
  155. package/dist/C_Guide2.js.map +1 -1
  156. package/dist/C_Icon.js.map +1 -1
  157. package/dist/C_Icon2.js +1 -1
  158. package/dist/C_Icon2.js.map +1 -1
  159. package/dist/{C_ImageCropper-D3L2-J_J.css.map → C_ImageCropper-BqZpkZfU.css.map} +1 -1
  160. package/dist/{C_ImageCropper-DrmUlaLi.css.map → C_ImageCropper-CylwGuzS.css.map} +1 -1
  161. package/dist/C_ImageCropper.cjs +1 -1
  162. package/dist/C_ImageCropper.css +10 -10
  163. package/dist/C_ImageCropper.js +1 -1
  164. package/dist/C_ImageCropper.js.map +1 -1
  165. package/dist/C_ImageCropper2.js +1 -1
  166. package/dist/C_ImageCropper2.js.map +1 -1
  167. package/dist/C_Language.cjs +1 -1
  168. package/dist/C_Language.js +1 -1
  169. package/dist/C_Language.js.map +1 -1
  170. package/dist/C_Language2.js +1 -1
  171. package/dist/C_Language2.js.map +1 -1
  172. package/dist/{C_Login-Cst_W1XC.css.map → C_Login-BkdnkBKX.css.map} +1 -1
  173. package/dist/{C_Login-DWZ_6K1x.css.map → C_Login-VkMM6OJ2.css.map} +1 -1
  174. package/dist/C_Login.cjs +1 -1
  175. package/dist/C_Login.css +72 -72
  176. package/dist/C_Login.js +1 -1
  177. package/dist/C_Login.js.map +1 -1
  178. package/dist/C_Login2.js +1 -1
  179. package/dist/C_Login2.js.map +1 -1
  180. package/dist/{C_Map-BCJmDnJT.css.map → C_Map-DNnBcY70.css.map} +1 -1
  181. package/dist/{C_Map-WUMXSAfy.css.map → C_Map-LEXIx6zM.css.map} +1 -1
  182. package/dist/C_Map.css +4 -4
  183. package/dist/C_Map.js.map +1 -1
  184. package/dist/C_Map2.js +1 -1
  185. package/dist/C_Map2.js.map +1 -1
  186. package/dist/{C_Markdown-7J0uPEuk.css.map → C_Markdown-DwmI0_0Q.css.map} +1 -1
  187. package/dist/{C_Markdown-C7Lg0_9z.css.map → C_Markdown-k0794RW0.css.map} +1 -1
  188. package/dist/C_Markdown.css +33 -33
  189. package/dist/C_Markdown.js.map +1 -1
  190. package/dist/C_Markdown2.js +1 -1
  191. package/dist/C_Markdown2.js.map +1 -1
  192. package/dist/C_Menu.js.map +1 -1
  193. package/dist/C_Menu2.js +1 -1
  194. package/dist/C_Menu2.js.map +1 -1
  195. package/dist/C_NotificationCenter.cjs +1 -1
  196. package/dist/C_NotificationCenter.js +1 -1
  197. package/dist/C_NotificationCenter.js.map +1 -1
  198. package/dist/C_NotificationCenter2.js +1 -1
  199. package/dist/C_NotificationCenter2.js.map +1 -1
  200. package/dist/C_OrgChart.js.map +1 -1
  201. package/dist/C_OrgChart2.js +1 -1
  202. package/dist/C_OrgChart2.js.map +1 -1
  203. package/dist/C_Progress.js.map +1 -1
  204. package/dist/C_Progress2.js +1 -1
  205. package/dist/C_Progress2.js.map +1 -1
  206. package/dist/{C_QRCode-DMxSyogU.css.map → C_QRCode-CFNTda_1.css.map} +1 -1
  207. package/dist/{C_QRCode-G7fiAkm4.css.map → C_QRCode-CmWr9lK-.css.map} +1 -1
  208. package/dist/C_QRCode.css +9 -9
  209. package/dist/C_QRCode.js.map +1 -1
  210. package/dist/C_QRCode2.js +1 -1
  211. package/dist/C_QRCode2.js.map +1 -1
  212. package/dist/{C_Signature-BJMvVPWT.css.map → C_Signature-BDx4ctsE.css.map} +1 -1
  213. package/dist/{C_Signature-BJUHx2BF.css.map → C_Signature-Bz_uNbwv.css.map} +1 -1
  214. package/dist/C_Signature.cjs +1 -1
  215. package/dist/C_Signature.css +15 -15
  216. package/dist/C_Signature.js +1 -1
  217. package/dist/C_Signature.js.map +1 -1
  218. package/dist/C_Signature2.js +1 -1
  219. package/dist/C_Signature2.js.map +1 -1
  220. package/dist/C_Skeleton.js.map +1 -1
  221. package/dist/C_Skeleton2.js +1 -1
  222. package/dist/C_Skeleton2.js.map +1 -1
  223. package/dist/{C_SplitPane-Br2eK8IG.css.map → C_SplitPane-BOwr1C7K.css.map} +1 -1
  224. package/dist/{C_SplitPane-DuyzUhKB.css.map → C_SplitPane-N-a_D-7F.css.map} +1 -1
  225. package/dist/C_SplitPane.cjs +1 -1
  226. package/dist/C_SplitPane.css +31 -31
  227. package/dist/C_SplitPane.js +1 -1
  228. package/dist/C_SplitPane.js.map +1 -1
  229. package/dist/C_SplitPane2.js +1 -1
  230. package/dist/C_SplitPane2.js.map +1 -1
  231. package/dist/C_Steps-Bk1krgiR.css.map +1 -0
  232. package/dist/C_Steps-Dn2CMpy1.css.map +1 -0
  233. package/dist/C_Steps.css +38 -38
  234. package/dist/C_Steps.js.map +1 -1
  235. package/dist/C_Steps2.js +1 -1
  236. package/dist/C_Steps2.js.map +1 -1
  237. package/dist/C_Table.cjs +1 -1
  238. package/dist/C_Table.js +1 -1
  239. package/dist/C_Table.js.map +1 -1
  240. package/dist/C_Table2.js +2 -2
  241. package/dist/C_Table2.js.map +1 -1
  242. package/dist/{C_TagsView-BsutyC3U.css.map → C_TagsView-DX3LecK1.css.map} +1 -1
  243. package/dist/{C_TagsView-Crm7yWg9.css.map → C_TagsView-DqOTa8bL.css.map} +1 -1
  244. package/dist/C_TagsView.cjs +1 -1
  245. package/dist/C_TagsView.css +36 -36
  246. package/dist/C_TagsView.js +1 -1
  247. package/dist/C_TagsView.js.map +1 -1
  248. package/dist/C_TagsView2.js +1 -1
  249. package/dist/C_TagsView2.js.map +1 -1
  250. package/dist/C_Theme.cjs +1 -1
  251. package/dist/C_Theme.js +1 -1
  252. package/dist/C_Theme.js.map +1 -1
  253. package/dist/C_Theme2.js +1 -1
  254. package/dist/C_Theme2.js.map +1 -1
  255. package/dist/C_Time-BzyQVvTS.css.map +1 -0
  256. package/dist/C_Time-DmpKLQHc.css.map +1 -0
  257. package/dist/C_Time.css +5 -5
  258. package/dist/C_Time.js.map +1 -1
  259. package/dist/C_Time2.js +1 -1
  260. package/dist/C_Time2.js.map +1 -1
  261. package/dist/{C_Timeline-DG70WtJP.css.map → C_Timeline-BKkimrZx.css.map} +1 -1
  262. package/dist/{C_Timeline-Dzxmmdjg.css.map → C_Timeline-DTuSCX6p.css.map} +1 -1
  263. package/dist/C_Timeline.cjs +1 -1
  264. package/dist/C_Timeline.css +45 -45
  265. package/dist/C_Timeline.js +1 -1
  266. package/dist/C_Timeline.js.map +1 -1
  267. package/dist/C_Timeline2.js +1 -1
  268. package/dist/C_Timeline2.js.map +1 -1
  269. package/dist/{C_Transfer-CCEqnC-v.css.map → C_Transfer-BOB6OBqS.css.map} +1 -1
  270. package/dist/{C_Transfer-CStPm4NP.css.map → C_Transfer-Dpq7ezWC.css.map} +1 -1
  271. package/dist/C_Transfer.cjs +1 -1
  272. package/dist/C_Transfer.css +31 -31
  273. package/dist/C_Transfer.js +1 -1
  274. package/dist/C_Transfer.js.map +1 -1
  275. package/dist/C_Transfer2.js +1 -1
  276. package/dist/C_Transfer2.js.map +1 -1
  277. package/dist/{C_Tree-B-Le4hjQ.css.map → C_Tree-D98nX9qT.css.map} +1 -1
  278. package/dist/{C_Tree-DnGc_MPb.css.map → C_Tree-ulfm7b-P.css.map} +1 -1
  279. package/dist/C_Tree.cjs +1 -1
  280. package/dist/C_Tree.css +33 -33
  281. package/dist/C_Tree.js +1 -1
  282. package/dist/C_Tree.js.map +1 -1
  283. package/dist/C_Tree2.js +1 -1
  284. package/dist/C_Tree2.js.map +1 -1
  285. package/dist/{C_Upload-CFAxVGVz.css.map → C_Upload-BR9fg5r4.css.map} +1 -1
  286. package/dist/{C_Upload-D8_QeSV0.css.map → C_Upload-CPqf74Ea.css.map} +1 -1
  287. package/dist/C_Upload.cjs +1 -1
  288. package/dist/C_Upload.css +4 -4
  289. package/dist/C_Upload.js +1 -1
  290. package/dist/C_Upload.js.map +1 -1
  291. package/dist/C_Upload2.js +2 -2
  292. package/dist/C_Upload2.js.map +1 -1
  293. package/dist/{C_VideoPlayer-Cdgv4Zq0.css.map → C_VideoPlayer-4J96tKfK.css.map} +1 -1
  294. package/dist/{C_VideoPlayer-rm0MODUv.css.map → C_VideoPlayer-D35seHkm.css.map} +1 -1
  295. package/dist/C_VideoPlayer.css +13 -13
  296. package/dist/C_VideoPlayer.js.map +1 -1
  297. package/dist/C_VideoPlayer2.js +3 -3
  298. package/dist/C_VideoPlayer2.js.map +1 -1
  299. package/dist/{C_VtableGantt-BpY-Rng3.css.map → C_VtableGantt-C2lxFmWg.css.map} +1 -1
  300. package/dist/{C_VtableGantt-DB87-jdS.css.map → C_VtableGantt-Dwnkw_WL.css.map} +1 -1
  301. package/dist/C_VtableGantt.cjs +1 -1
  302. package/dist/C_VtableGantt.css +15 -15
  303. package/dist/C_VtableGantt.js +1 -1
  304. package/dist/C_VtableGantt.js.map +1 -1
  305. package/dist/C_VtableGantt2.js +1 -1
  306. package/dist/C_VtableGantt2.js.map +1 -1
  307. package/dist/C_WaterFall.js.map +1 -1
  308. package/dist/C_WaterFall2.js +1 -1
  309. package/dist/C_WaterFall2.js.map +1 -1
  310. package/dist/{C_WorkFlow-7F6op6qN.css.map → C_WorkFlow-2hJfvvTK.css.map} +1 -1
  311. package/dist/{C_WorkFlow-Cy3HWA6A.css.map → C_WorkFlow-DHoNjl8-.css.map} +1 -1
  312. package/dist/C_WorkFlow.cjs +1 -1
  313. package/dist/C_WorkFlow.css +108 -108
  314. package/dist/C_WorkFlow.js +1 -1
  315. package/dist/C_WorkFlow.js.map +1 -1
  316. package/dist/C_WorkFlow2.js +1 -1
  317. package/dist/C_WorkFlow2.js.map +1 -1
  318. package/dist/constants.d.ts +3 -3
  319. package/dist/constants2.d.ts +4 -4
  320. package/dist/constants3.d.ts +3 -3
  321. package/dist/constants4.d.ts +4 -4
  322. package/dist/constants5.d.ts +2 -2
  323. package/dist/data.d.ts +2 -2
  324. package/dist/index.cjs.map +1 -1
  325. package/dist/index.js.map +1 -1
  326. package/dist/index.vue.d.ts +1 -1
  327. package/dist/index10.vue.d.ts +1 -1
  328. package/dist/index11.vue.d.ts +4 -4
  329. package/dist/index12.vue.d.ts +1 -1
  330. package/dist/index13.vue.d.ts +2 -2
  331. package/dist/index14.vue.d.ts +3 -3
  332. package/dist/index15.vue.d.ts +3 -3
  333. package/dist/index16.vue.d.ts +2 -2
  334. package/dist/index17.vue.d.ts +1 -1
  335. package/dist/index18.vue.d.ts +5 -5
  336. package/dist/index2.vue.d.ts +1 -1
  337. package/dist/index20.vue.d.ts +1 -1
  338. package/dist/index22.vue.d.ts +1 -1
  339. package/dist/index23.vue.d.ts +2 -2
  340. package/dist/index24.vue.d.ts +1 -1
  341. package/dist/index26.vue.d.ts +3 -3
  342. package/dist/index27.vue.d.ts +2 -2
  343. package/dist/index28.vue.d.ts +3 -3
  344. package/dist/index3.vue.d.ts +3 -3
  345. package/dist/index4.vue.d.ts +2 -2
  346. package/dist/index6.vue.d.ts +6 -6
  347. package/dist/index7.vue.d.ts +2 -2
  348. package/dist/index8.vue.d.ts +1 -1
  349. package/dist/index9.vue.d.ts +2 -2
  350. package/dist/menuAdapter.js.map +1 -1
  351. package/dist/resolver.cjs.map +1 -1
  352. package/dist/resolver.js.map +1 -1
  353. package/dist/style.css +1483 -1483
  354. package/dist/themes/glass-morphism.css +1 -0
  355. package/dist/useCalendarEvents.d.ts +1 -1
  356. package/dist/useCollapsePanel.d.ts +1 -1
  357. package/dist/useCropperCore.d.ts +2 -2
  358. package/dist/useDraggableLayout.d.ts +4 -4
  359. package/dist/useDynamicFormState.d.ts +21 -21
  360. package/dist/useEdgeInteraction.d.ts +2 -2
  361. package/dist/useModalEdit.d.ts +1 -1
  362. package/dist/useQRCode.d.ts +3 -3
  363. package/dist/useSearchState.d.ts +2 -2
  364. package/dist/useSignatureHistory.d.ts +4 -4
  365. package/dist/useSplitResize.d.ts +2 -2
  366. package/dist/useTimeSelection.d.ts +2 -2
  367. package/dist/useTreeOperations.d.ts +3 -3
  368. package/dist/useWorkflowValidation.d.ts +6 -6
  369. package/package.json +11 -8
  370. package/dist/C_ActionBar-jZPsiXtT.css.map +0 -1
  371. package/dist/C_ActionBar-nnfbZCea.css.map +0 -1
  372. package/dist/C_Code-DPZlNSxL.css.map +0 -1
  373. package/dist/C_Code-avZjAnHD.css.map +0 -1
  374. package/dist/C_Editor-C49qURgb.css.map +0 -1
  375. package/dist/C_Editor-DuxBD9Qg.css.map +0 -1
  376. package/dist/C_FullCalendar-1U4VlG7X.css.map +0 -1
  377. package/dist/C_FullCalendar-DLUdCtqf.css.map +0 -1
  378. package/dist/C_Steps-BHYNJI1l.css.map +0 -1
  379. package/dist/C_Steps-DY7vl-4I.css.map +0 -1
  380. package/dist/C_Time-Bd_e1YDN.css.map +0 -1
  381. package/dist/C_Time-CKb_fwdm.css.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"C_FilePreview.js","names":["XLSX","totalPages","pdfUrl","headings","content","sheets","$emit"],"sources":["../src/components/C_FilePreview/data.ts","../src/components/C_FilePreview/components/PdfViewer/index.vue","../src/components/C_FilePreview/components/PdfViewer/index.vue","../src/components/C_FilePreview/components/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","/* unplugin-vue-components disabled */<!--\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 as any\"\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\r\n size=\"small\"\r\n @click=\"adjustZoom('reset')\"\r\n >\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\n import { ref } from 'vue'\r\n import { NButton, NInputNumber } from 'naive-ui'\r\n import { createZoomHandler, ZOOM_CONFIGS } from '../../data'\r\n\r\n const props = defineProps<{\r\n pdfUrl: string\r\n totalPages: number\r\n }>()\r\n\r\n const currentPage = ref(1)\r\n const scale = ref(1)\r\n\r\n const adjustZoom = createZoomHandler(scale, ZOOM_CONFIGS.pdf)\r\n\r\n const 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","/* unplugin-vue-components disabled */<!--\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 as any\"\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\r\n size=\"small\"\r\n @click=\"adjustZoom('reset')\"\r\n >\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\n import { ref } from 'vue'\r\n import { NButton, NInputNumber } from 'naive-ui'\r\n import { createZoomHandler, ZOOM_CONFIGS } from '../../data'\r\n\r\n const props = defineProps<{\r\n pdfUrl: string\r\n totalPages: number\r\n }>()\r\n\r\n const currentPage = ref(1)\r\n const scale = ref(1)\r\n\r\n const adjustZoom = createZoomHandler(scale, ZOOM_CONFIGS.pdf)\r\n\r\n const 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 as any\"\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\r\n size=\"small\"\r\n @click=\"adjustZoom('reset')\"\r\n >\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\n import { ref } from 'vue'\r\n import { NButton, NInputNumber } from 'naive-ui'\r\n import { createZoomHandler, ZOOM_CONFIGS } from '../../data'\r\n\r\n const props = defineProps<{\r\n pdfUrl: string\r\n totalPages: number\r\n }>()\r\n\r\n const currentPage = ref(1)\r\n const scale = ref(1)\r\n\r\n const adjustZoom = createZoomHandler(scale, ZOOM_CONFIGS.pdf)\r\n\r\n const 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","/* unplugin-vue-components disabled */<!--\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","/* unplugin-vue-components disabled */<!--\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","/* unplugin-vue-components disabled */<!--\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","/* unplugin-vue-components disabled */<!--\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","/* unplugin-vue-components disabled */<!--\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\r\n v-if=\"!autoPreview\"\r\n class=\"file-info-card\"\r\n >\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\r\n :type=\"fileConfig.tagType as any\"\r\n size=\"small\"\r\n >\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\r\n type=\"primary\"\r\n @click=\"openPreview\"\r\n >\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\r\n type=\"tertiary\"\r\n @click=\"downloadFile\"\r\n >\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\r\n ref=\"modalContainer\"\r\n class=\"modal-container\"\r\n >\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\r\n size=\"small\"\r\n type=\"tertiary\"\r\n @click=\"downloadFile\"\r\n >\r\n <template #icon>\r\n <C_Icon name=\"ic:outline-download\" />\r\n </template>\r\n 下载\r\n </NButton>\r\n <NButton\r\n size=\"small\"\r\n type=\"tertiary\"\r\n @click=\"showModal = false\"\r\n >\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\r\n :type=\"fileConfig.tagType as any\"\r\n size=\"small\"\r\n >\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\r\n size=\"small\"\r\n type=\"primary\"\r\n @click=\"toggleFullscreen\"\r\n >\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\r\n v-if=\"loading\"\r\n size=\"large\"\r\n >\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\n import { ref, toRefs, watch } from 'vue'\r\n import { NButton, NEllipsis, NTag, NModal, NSpin, NResult } from 'naive-ui'\r\n import { formatFileSize } from './data'\r\n import PdfViewer from './components/PdfViewer/index.vue'\r\n import WordViewer from './components/WordViewer/index.vue'\r\n import ExcelViewer from './components/ExcelViewer/index.vue'\r\n import { useFilePreview } from './composables/useFilePreview'\r\n import { useFullscreen } from './composables/useFullscreen'\r\n\r\n defineOptions({ name: 'C_FilePreview' })\r\n\r\n const 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\n const { file, url, fileName: propFileName, autoPreview } = toRefs(props)\r\n\r\n const emit = defineEmits<{\r\n preview: [file: File | string]\r\n download: [file: File | string]\r\n }>()\r\n\r\n /* ==================== Composables ==================== */\r\n const {\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\n const modalContainer = ref<HTMLElement>()\r\n const { isFullscreen, toggleFullscreen, exitFullscreen } =\r\n useFullscreen(modalContainer)\r\n\r\n /* ==================== Modal 关闭时退出全屏 ==================== */\r\n watch(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","/* unplugin-vue-components disabled */<!--\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\r\n v-if=\"!autoPreview\"\r\n class=\"file-info-card\"\r\n >\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\r\n :type=\"fileConfig.tagType as any\"\r\n size=\"small\"\r\n >\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\r\n type=\"primary\"\r\n @click=\"openPreview\"\r\n >\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\r\n type=\"tertiary\"\r\n @click=\"downloadFile\"\r\n >\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\r\n ref=\"modalContainer\"\r\n class=\"modal-container\"\r\n >\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\r\n size=\"small\"\r\n type=\"tertiary\"\r\n @click=\"downloadFile\"\r\n >\r\n <template #icon>\r\n <C_Icon name=\"ic:outline-download\" />\r\n </template>\r\n 下载\r\n </NButton>\r\n <NButton\r\n size=\"small\"\r\n type=\"tertiary\"\r\n @click=\"showModal = false\"\r\n >\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\r\n :type=\"fileConfig.tagType as any\"\r\n size=\"small\"\r\n >\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\r\n size=\"small\"\r\n type=\"primary\"\r\n @click=\"toggleFullscreen\"\r\n >\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\r\n v-if=\"loading\"\r\n size=\"large\"\r\n >\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\n import { ref, toRefs, watch } from 'vue'\r\n import { NButton, NEllipsis, NTag, NModal, NSpin, NResult } from 'naive-ui'\r\n import { formatFileSize } from './data'\r\n import PdfViewer from './components/PdfViewer/index.vue'\r\n import WordViewer from './components/WordViewer/index.vue'\r\n import ExcelViewer from './components/ExcelViewer/index.vue'\r\n import { useFilePreview } from './composables/useFilePreview'\r\n import { useFullscreen } from './composables/useFullscreen'\r\n\r\n defineOptions({ name: 'C_FilePreview' })\r\n\r\n const 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\n const { file, url, fileName: propFileName, autoPreview } = toRefs(props)\r\n\r\n const emit = defineEmits<{\r\n preview: [file: File | string]\r\n download: [file: File | string]\r\n }>()\r\n\r\n /* ==================== Composables ==================== */\r\n const {\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\n const modalContainer = ref<HTMLElement>()\r\n const { isFullscreen, toggleFullscreen, exitFullscreen } =\r\n useFullscreen(modalContainer)\r\n\r\n /* ==================== Modal 关闭时退出全屏 ==================== */\r\n watch(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\r\n v-if=\"!autoPreview\"\r\n class=\"file-info-card\"\r\n >\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\r\n :type=\"fileConfig.tagType as any\"\r\n size=\"small\"\r\n >\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\r\n type=\"primary\"\r\n @click=\"openPreview\"\r\n >\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\r\n type=\"tertiary\"\r\n @click=\"downloadFile\"\r\n >\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\r\n ref=\"modalContainer\"\r\n class=\"modal-container\"\r\n >\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\r\n size=\"small\"\r\n type=\"tertiary\"\r\n @click=\"downloadFile\"\r\n >\r\n <template #icon>\r\n <C_Icon name=\"ic:outline-download\" />\r\n </template>\r\n 下载\r\n </NButton>\r\n <NButton\r\n size=\"small\"\r\n type=\"tertiary\"\r\n @click=\"showModal = false\"\r\n >\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\r\n :type=\"fileConfig.tagType as any\"\r\n size=\"small\"\r\n >\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\r\n size=\"small\"\r\n type=\"primary\"\r\n @click=\"toggleFullscreen\"\r\n >\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\r\n v-if=\"loading\"\r\n size=\"large\"\r\n >\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\n import { ref, toRefs, watch } from 'vue'\r\n import { NButton, NEllipsis, NTag, NModal, NSpin, NResult } from 'naive-ui'\r\n import { formatFileSize } from './data'\r\n import PdfViewer from './components/PdfViewer/index.vue'\r\n import WordViewer from './components/WordViewer/index.vue'\r\n import ExcelViewer from './components/ExcelViewer/index.vue'\r\n import { useFilePreview } from './composables/useFilePreview'\r\n import { useFullscreen } from './composables/useFullscreen'\r\n\r\n defineOptions({ name: 'C_FilePreview' })\r\n\r\n const 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\n const { file, url, fileName: propFileName, autoPreview } = toRefs(props)\r\n\r\n const emit = defineEmits<{\r\n preview: [file: File | string]\r\n download: [file: File | string]\r\n }>()\r\n\r\n /* ==================== Composables ==================== */\r\n const {\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\n const modalContainer = ref<HTMLElement>()\r\n const { isFullscreen, toggleFullscreen, exitFullscreen } =\r\n useFullscreen(modalContainer)\r\n\r\n /* ==================== Modal 关闭时退出全屏 ==================== */\r\n watch(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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"}
1
+ {"version":3,"file":"C_FilePreview.js","names":["XLSX"],"sources":["../src/components/C_FilePreview/data.ts","../src/components/C_FilePreview/components/PdfViewer/index.vue","../src/components/C_FilePreview/components/WordViewer/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"],"sourcesContent":["/**\r\n * C_FilePreview 常量配置与工具函数\r\n * 类型定义统一在 ./types.ts\r\n */\r\nimport { type Ref } from \"vue\";\r\nimport * as XLSX from \"xlsx\";\r\nimport mammoth from \"mammoth\";\r\nimport type {\r\n FilePreviewType,\r\n FileConfig,\r\n ZoomConfig,\r\n ExcelRow,\r\n ExcelColumn,\r\n ExcelSheet,\r\n DocHeading,\r\n PdfLoadResult,\r\n WordLoadResult,\r\n ExcelLoadResult,\r\n} from \"./types\";\r\n\r\n/* ==================== 常量配置 ==================== */\r\n\r\nexport const FILE_TYPE_MAP: Record<string, FilePreviewType> = {\r\n pdf: \"pdf\",\r\n doc: \"word\",\r\n docx: \"word\",\r\n xls: \"excel\",\r\n xlsx: \"excel\",\r\n};\r\n\r\nexport const FILE_CONFIGS: Record<string, FileConfig> = {\r\n pdf: {\r\n tagType: \"error\",\r\n icon: \"ic:outline-picture-as-pdf\",\r\n color: \"#dc2626\",\r\n },\r\n word: { tagType: \"info\", icon: \"ic:outline-description\", color: \"#2563eb\" },\r\n excel: { tagType: \"success\", icon: \"ic:outline-grid-on\", color: \"#16a34a\" },\r\n unknown: {\r\n tagType: \"default\",\r\n icon: \"ic:outline-insert-drive-file\",\r\n color: \"#6b7280\",\r\n },\r\n};\r\n\r\nexport const ZOOM_CONFIGS: Record<string, ZoomConfig> = {\r\n pdf: { min: 0.5, max: 3, step: 0.25, default: 1 },\r\n word: { min: 50, max: 200, step: 10, default: 100 },\r\n};\r\n\r\nexport const PAGE_SIZE_OPTIONS = [20, 50, 100, 200];\r\n\r\nexport const FULLSCREEN_EVENTS = [\r\n \"fullscreenchange\",\r\n \"webkitfullscreenchange\",\r\n \"mozfullscreenchange\",\r\n \"MSFullscreenChange\",\r\n];\r\n\r\n/* ==================== 文件信息工具函数 ==================== */\r\n\r\nexport const extractFileNameFromUrl = (url: string): string => {\r\n try {\r\n const urlPath = url.split(\"/\").pop() || url.split(\"\\\\\").pop();\r\n if (urlPath?.includes(\".\")) {\r\n const decodedName = decodeURIComponent(urlPath.split(\"?\")[0]);\r\n if (decodedName && decodedName !== url) return decodedName;\r\n }\r\n } catch (error) {\r\n console.warn(\"解析URL文件名失败:\", error);\r\n }\r\n return \"未知文件\";\r\n};\r\n\r\nexport const formatFileSize = (bytes: number): string => {\r\n if (bytes === 0) return \"0 B\";\r\n const k = 1024;\r\n const sizes = [\"B\", \"KB\", \"MB\", \"GB\"];\r\n const i = Math.floor(Math.log(bytes) / Math.log(k));\r\n return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + \" \" + sizes[i];\r\n};\r\n\r\nexport const getFileType = (fileName: string): FilePreviewType => {\r\n if (!fileName || fileName === \"未知文件\") return \"unknown\";\r\n const ext = fileName.toLowerCase().split(\".\").pop();\r\n if (!ext) return \"unknown\";\r\n return FILE_TYPE_MAP[ext] || \"unknown\";\r\n};\r\n\r\nexport const getFileConfig = (fileType: string): FileConfig => {\r\n return FILE_CONFIGS[fileType] || FILE_CONFIGS.unknown;\r\n};\r\n\r\n/* ==================== 缩放工具 ==================== */\r\n\r\nexport const createZoomHandler = (\r\n valueRef: Ref<number>,\r\n config: ZoomConfig,\r\n) => {\r\n return (action: \"in\" | \"out\" | \"reset\") => {\r\n const { min, max, step, default: defaultValue } = config;\r\n switch (action) {\r\n case \"reset\":\r\n valueRef.value = defaultValue;\r\n break;\r\n case \"in\":\r\n if (valueRef.value < max) valueRef.value += step;\r\n break;\r\n case \"out\":\r\n if (valueRef.value > min) valueRef.value -= step;\r\n break;\r\n }\r\n };\r\n};\r\n\r\n/* ==================== Excel 工具函数 ==================== */\r\n\r\nexport const getColumnLetter = (index: number): string => {\r\n let result = \"\";\r\n while (index >= 0) {\r\n result = String.fromCharCode(65 + (index % 26)) + result;\r\n index = Math.floor(index / 26) - 1;\r\n }\r\n return result;\r\n};\r\n\r\nexport const formatCellValue = (value: any): string => {\r\n if (!value) return \"\";\r\n const strValue = String(value).trim();\r\n\r\n if (!isNaN(Number(strValue)) && strValue !== \"\" && strValue.length < 15) {\r\n const num = Number(strValue);\r\n return Number.isInteger(num)\r\n ? num.toLocaleString()\r\n : num.toLocaleString(undefined, { maximumFractionDigits: 2 });\r\n }\r\n return strValue;\r\n};\r\n\r\nexport const getCellClass = (value: any): string => {\r\n if (!value) return \"cell-empty\";\r\n const strValue = String(value).trim();\r\n\r\n if (!isNaN(Number(strValue)) && strValue !== \"\") return \"cell-number\";\r\n if (strValue.match(/[■▬▪▫─━]/)) return \"cell-gantt\";\r\n if (\r\n strValue.match(/^\\d{4}[-/]\\d{2}[-/]\\d{2}/) ||\r\n strValue.match(/^\\d{2}[-/]\\d{2}[-/]\\d{4}/)\r\n )\r\n return \"cell-date\";\r\n if ([\"true\", \"false\"].includes(strValue.toLowerCase())) return \"cell-boolean\";\r\n return strValue.length > 20 ? \"cell-text cell-long\" : \"cell-text\";\r\n};\r\n\r\nexport const processExcelSheet = (\r\n worksheet: any,\r\n merges: any[],\r\n): { data: ExcelRow[]; columns: ExcelColumn[] } => {\r\n const range = XLSX.utils.decode_range(worksheet[\"!ref\"] || \"A1:A1\");\r\n const { c: maxCol, r: maxRow } = range.e;\r\n\r\n const columns: ExcelColumn[] = Array.from({ length: maxCol + 1 }, (_, c) => {\r\n const cellAddress = XLSX.utils.encode_cell({ r: 0, c });\r\n const cell = worksheet[cellAddress];\r\n const columnName = cell ? String(cell.v || \"\").trim() : `列${c + 1}`;\r\n return {\r\n title: columnName || `列${c + 1}`,\r\n key: `col_${c}`,\r\n width: Math.min(Math.max(columnName.length * 12, 80), 200),\r\n };\r\n });\r\n\r\n const mergeMap = new Map();\r\n merges.forEach(({ s: { r: sRow, c: sCol }, e: { r: eRow, c: eCol } }) => {\r\n for (let r = sRow; r <= eRow; r++) {\r\n for (let c = sCol; c <= eCol; c++) {\r\n mergeMap.set(`${r}-${c}`, {\r\n isMain: r === sRow && c === sCol,\r\n rowspan: eRow - sRow + 1,\r\n colspan: eCol - sCol + 1,\r\n });\r\n }\r\n }\r\n });\r\n\r\n const data: ExcelRow[] = Array.from({ length: maxRow + 1 }, (_, r) => {\r\n const row: ExcelRow = {};\r\n for (let c = 0; c <= maxCol; c++) {\r\n const cellAddress = XLSX.utils.encode_cell({ r, c });\r\n const cell = worksheet[cellAddress];\r\n const mergeInfo = mergeMap.get(`${r}-${c}`);\r\n\r\n row[`col_${c}`] = {\r\n value: cell ? cell.v || \"\" : \"\",\r\n merged: !!mergeInfo,\r\n hidden: mergeInfo && !mergeInfo.isMain,\r\n rowspan: mergeInfo?.isMain ? mergeInfo.rowspan : 1,\r\n colspan: mergeInfo?.isMain ? mergeInfo.colspan : 1,\r\n };\r\n }\r\n return row;\r\n });\r\n\r\n return { data, columns };\r\n};\r\n\r\n/* ==================== 文件加载器 ==================== */\r\n\r\nexport async function loadPdf(file: File): Promise<PdfLoadResult> {\r\n const fileUrl = URL.createObjectURL(file);\r\n return {\r\n url: fileUrl + \"#toolbar=1&navpanes=1&scrollbar=1&view=FitH\",\r\n totalPages: 1,\r\n };\r\n}\r\n\r\nexport async function loadWord(file: File): Promise<WordLoadResult> {\r\n const arrayBuffer = await file.arrayBuffer();\r\n const result = await mammoth.convertToHtml({\r\n arrayBuffer,\r\n styleMap: [\r\n \"p[style-name='Heading 1'] => h1:fresh\",\r\n \"p[style-name='Heading 2'] => h2:fresh\",\r\n \"p[style-name='Heading 3'] => h3:fresh\",\r\n \"p[style-name='Title'] => h1.title:fresh\",\r\n ],\r\n } as any);\r\n\r\n let content = result.value;\r\n const headings: DocHeading[] = [];\r\n\r\n /* 提取标题并注入 id */\r\n const tempDiv = document.createElement(\"div\");\r\n tempDiv.innerHTML = content;\r\n const headingElements = tempDiv.querySelectorAll(\"h1, h2, h3, h4, h5, h6\");\r\n\r\n Array.from(headingElements).forEach((el, index) => {\r\n const id = `heading-${index}`;\r\n const level = parseInt(el.tagName.charAt(1));\r\n const text = el.textContent || \"\";\r\n\r\n content = content.replace(\r\n el.outerHTML,\r\n el.outerHTML.replace(\r\n el.tagName.toLowerCase(),\r\n `${el.tagName.toLowerCase()} id=\"${id}\"`,\r\n ),\r\n );\r\n\r\n headings.push({ id, text, level });\r\n });\r\n\r\n return { content, headings };\r\n}\r\n\r\nexport async function loadExcel(file: File): Promise<ExcelLoadResult> {\r\n const arrayBuffer = await file.arrayBuffer();\r\n const workbook = XLSX.read(arrayBuffer, {\r\n type: \"array\",\r\n cellStyles: true,\r\n cellFormula: true,\r\n cellDates: true,\r\n });\r\n\r\n if (!workbook.SheetNames.length) {\r\n throw new Error(\"Excel文件中没有找到工作表\");\r\n }\r\n\r\n const sheets: ExcelSheet[] = workbook.SheetNames.map((name) => {\r\n const worksheet = workbook.Sheets[name];\r\n const merges = worksheet[\"!merges\"] || [];\r\n const { data, columns } = processExcelSheet(worksheet, merges);\r\n return { name, data, merges, columns };\r\n });\r\n\r\n return { sheets };\r\n}\r\n","<!--\n PdfViewer — PDF 文件预览子组件\n 负责: 工具栏(翻页+缩放) + iframe 渲染\n-->\n<template>\n <div class=\"file-container pdf-container\">\n <div class=\"file-toolbar\">\n <div class=\"flex justify-between items-center\">\n <!-- 翻页控制 -->\n <div class=\"flex gap-2 items-center\">\n <NButton\n size=\"small\"\n :disabled=\"currentPage <= 1\"\n @click=\"changePage('prev')\"\n >\n <template #icon>\n <C_Icon name=\"ic:outline-chevron-left\" />\n </template>\n </NButton>\n <NInputNumber\n v-model:value=\"currentPage\"\n size=\"small\"\n :min=\"1\"\n :max=\"totalPages\"\n style=\"width: 80px\"\n @update:value=\"changePage as any\"\n />\n <span class=\"text-sm text-gray-600\">/ {{ totalPages }}</span>\n <NButton\n size=\"small\"\n :disabled=\"currentPage >= totalPages\"\n @click=\"changePage('next')\"\n >\n <template #icon>\n <C_Icon name=\"ic:outline-chevron-right\" />\n </template>\n </NButton>\n </div>\n\n <!-- 缩放控制 -->\n <div class=\"flex gap-2 items-center\">\n <NButton\n size=\"small\"\n :disabled=\"scale <= 0.5\"\n @click=\"adjustZoom('out')\"\n >\n <template #icon>\n <C_Icon name=\"ic:outline-zoom-out\" />\n </template>\n </NButton>\n <span class=\"text-sm text-gray-600 min-w-12 text-center\">\n {{ Math.round(scale * 100) }}%\n </span>\n <NButton\n size=\"small\"\n :disabled=\"scale >= 3\"\n @click=\"adjustZoom('in')\"\n >\n <template #icon>\n <C_Icon name=\"ic:outline-zoom-in\" />\n </template>\n </NButton>\n <NButton\n size=\"small\"\n @click=\"adjustZoom('reset')\"\n >\n <template #icon>\n <C_Icon name=\"ic:outline-fit-screen\" />\n </template>\n 适应\n </NButton>\n </div>\n </div>\n </div>\n\n <div class=\"file-viewer\">\n <iframe\n v-if=\"pdfUrl\"\n :src=\"pdfUrl\"\n class=\"w-full h-full border-0\"\n title=\"PDF预览\"\n frameborder=\"0\"\n allowfullscreen\n />\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\n import { ref } from 'vue'\n import { NButton, NInputNumber } from 'naive-ui'\n import { createZoomHandler, ZOOM_CONFIGS } from '../../data'\n\n const props = defineProps<{\n pdfUrl: string\n totalPages: number\n }>()\n\n const currentPage = ref(1)\n const scale = ref(1)\n\n const adjustZoom = createZoomHandler(scale, ZOOM_CONFIGS.pdf)\n\n const changePage = (action: 'prev' | 'next' | number) => {\n if (typeof action === 'number') {\n currentPage.value = Math.max(1, Math.min(action, props.totalPages))\n } else {\n const delta = action === 'prev' ? -1 : 1\n currentPage.value = Math.max(\n 1,\n Math.min(currentPage.value + delta, props.totalPages)\n )\n }\n }\n</script>\n\n<style lang=\"scss\" scoped>\n @use './index.scss';\n</style>\n","<!--\n WordViewer — Word 文档预览子组件\n 负责: 目录导航 + 缩放 + 文档内容渲染\n-->\n<template>\n <div class=\"file-container word-container\">\n <div class=\"file-toolbar\">\n <div class=\"flex gap-2 items-center\">\n <NButton size=\"small\" @click=\"showOutline = !showOutline\">\n <template #icon>\n <C_Icon name=\"ic:outline-list\" />\n </template>\n {{ showOutline ? \"隐藏\" : \"显示\" }}目录\n </NButton>\n <NDivider vertical />\n <NButton\n size=\"small\"\n :disabled=\"wordZoom <= 50\"\n @click=\"adjustWordZoom('out')\"\n >\n <template #icon>\n <C_Icon name=\"ic:outline-zoom-out\" />\n </template>\n </NButton>\n <span class=\"text-sm text-gray-600 min-w-12 text-center\">\n {{ wordZoom }}%\n </span>\n <NButton\n size=\"small\"\n :disabled=\"wordZoom >= 200\"\n @click=\"adjustWordZoom('in')\"\n >\n <template #icon>\n <C_Icon name=\"ic:outline-zoom-in\" />\n </template>\n </NButton>\n <NButton size=\"small\" @click=\"adjustWordZoom('reset')\">\n <template #icon>\n <C_Icon name=\"ic:outline-fit-screen\" />\n </template>\n 重置\n </NButton>\n </div>\n </div>\n\n <div class=\"word-layout\">\n <div class=\"word-main\">\n <!-- 侧边栏目录 -->\n <div v-if=\"showOutline\" class=\"word-outline\">\n <div class=\"outline-header\">\n <h3 class=\"text-sm font-semibold\">文档目录</h3>\n </div>\n <div class=\"outline-content\">\n <div\n v-for=\"(heading, index) in headings\"\n :key=\"index\"\n class=\"outline-item\"\n :class=\"`level-${heading.level}`\"\n @click=\"scrollToHeading(heading.id)\"\n >\n {{ heading.text }}\n </div>\n </div>\n </div>\n\n <!-- 主要内容区域 -->\n <div class=\"word-content\">\n <div\n class=\"word-document\"\n :style=\"{\n transform: `scale(${wordZoom / 100})`,\n transformOrigin: 'top center',\n }\"\n v-html=\"content\"\n ></div>\n </div>\n </div>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref } from \"vue\";\nimport { NButton, NDivider } from \"naive-ui\";\nimport { createZoomHandler, ZOOM_CONFIGS } from \"../../data\";\nimport type { DocHeading } from \"../../types\";\n\ndefineProps<{\n content: string;\n headings: DocHeading[];\n}>();\n\nconst showOutline = ref(true);\nconst wordZoom = ref(100);\n\nconst adjustWordZoom = createZoomHandler(wordZoom, ZOOM_CONFIGS.word);\n\nconst scrollToHeading = (headingId: string) => {\n document\n .getElementById(headingId)\n ?.scrollIntoView({ behavior: \"smooth\", block: \"start\" });\n};\n</script>\n\n<style lang=\"scss\" scoped>\n@use \"./index.scss\";\n</style>\n","<!--\n ExcelViewer — Excel 表格预览子组件\n 负责: 工作表切换 + 表格渲染(合并单元格) + 分页 + 格式切换\n-->\n<template>\n <div class=\"file-container excel-container\">\n <!-- 工具栏 -->\n <div class=\"file-toolbar\">\n <div class=\"flex justify-between items-center\">\n <div class=\"flex gap-2 items-center\">\n <NTabs\n v-if=\"sheets.length > 1\"\n v-model:value=\"activeSheet\"\n type=\"card\"\n size=\"small\"\n >\n <NTabPane\n v-for=\"sheet in sheets\"\n :key=\"sheet.name\"\n :name=\"sheet.name\"\n :tab=\"sheet.name\"\n />\n </NTabs>\n <span v-else class=\"text-sm text-gray-600\">\n 工作表: {{ activeSheet }}\n </span>\n </div>\n\n <div class=\"flex gap-2 items-center\">\n <NButton size=\"small\" @click=\"showExcelFormat = !showExcelFormat\">\n <template #icon>\n <C_Icon name=\"ic:outline-format-paint\" />\n </template>\n {{ showExcelFormat ? \"紧凑视图\" : \"完整格式\" }}\n </NButton>\n </div>\n </div>\n </div>\n\n <div class=\"excel-viewer\">\n <!-- 信息面板 -->\n <div v-if=\"currentData.length > 0\" class=\"excel-info\">\n <NText depth=\"3\" class=\"text-sm\">\n 当前工作表: {{ activeSheet }} | 总行数: {{ currentData.length }} |\n 总列数: {{ currentColumns.length }} | 当前页:\n {{ currentExcelPage }}/{{ totalExcelPages }}\n </NText>\n </div>\n\n <!-- 表格 -->\n <div class=\"excel-table-container\">\n <div\n class=\"excel-table-wrapper\"\n :class=\"{ 'simple-mode': !showExcelFormat }\"\n >\n <table v-if=\"currentData.length > 0\" class=\"excel-table\">\n <thead>\n <tr>\n <th class=\"row-number\">行号</th>\n <th\n v-for=\"(col, index) in currentColumns\"\n :key=\"col.key\"\n class=\"excel-header\"\n :style=\"{ minWidth: col.width + 'px' }\"\n >\n <div class=\"header-content\">\n <span class=\"column-letter\">{{\n getColumnLetter(index)\n }}</span>\n <span class=\"column-title\">{{ col.title }}</span>\n </div>\n </th>\n </tr>\n </thead>\n <tbody>\n <tr\n v-for=\"(row, rowIndex) in paginatedData\"\n :key=\"rowIndex\"\n class=\"excel-row\"\n >\n <td class=\"row-number\">\n {{ (currentExcelPage - 1) * pageSize + rowIndex + 1 }}\n </td>\n <td\n v-for=\"col in currentColumns\"\n :key=\"col.key\"\n v-show=\"!row[col.key]?.hidden\"\n class=\"excel-cell\"\n :class=\"[\n getCellClass(row[col.key]?.value),\n row[col.key]?.merged ? 'merged-cell' : '',\n !showExcelFormat ? 'compact-cell' : '',\n ]\"\n :rowspan=\"row[col.key]?.rowspan || 1\"\n :colspan=\"row[col.key]?.colspan || 1\"\n :title=\"row[col.key]?.value\"\n >\n {{ formatCellValue(row[col.key]?.value) }}\n </td>\n </tr>\n </tbody>\n </table>\n\n <div v-else class=\"excel-empty\">\n <NEmpty description=\"该工作表没有数据或解析失败\">\n <template #extra>\n <NButton size=\"small\" @click=\"$emit('reload')\">\n 重新解析\n </NButton>\n </template>\n </NEmpty>\n </div>\n </div>\n\n <!-- 分页 -->\n <div v-if=\"totalExcelPages > 1\" class=\"excel-pagination\">\n <NPagination\n v-model:page=\"currentExcelPage\"\n :page-count=\"totalExcelPages\"\n :page-size=\"pageSize\"\n show-size-picker\n :page-sizes=\"PAGE_SIZE_OPTIONS\"\n @update:page-size=\"handlePageSizeChange\"\n />\n </div>\n </div>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, computed, watch } from \"vue\";\nimport { NButton, NTabs, NTabPane, NText, NEmpty, NPagination } from \"naive-ui\";\nimport {\n getColumnLetter,\n formatCellValue,\n getCellClass,\n PAGE_SIZE_OPTIONS,\n} from \"../../data\";\nimport type { ExcelSheet, ExcelRow, ExcelColumn } from \"../../types\";\n\nconst props = defineProps<{\n sheets: ExcelSheet[];\n}>();\n\ndefineEmits<{\n reload: [];\n}>();\n\n/* ==================== 内部状态 ==================== */\nconst activeSheet = ref(\"\");\nconst showExcelFormat = ref(false);\nconst currentExcelPage = ref(1);\nconst pageSize = ref(50);\n\n/* ==================== 当前工作表数据 ==================== */\nconst currentData = ref<ExcelRow[]>([]);\nconst currentColumns = ref<ExcelColumn[]>([]);\n\n/* ==================== 计算属性 ==================== */\nconst totalExcelPages = computed(() =>\n Math.ceil(currentData.value.length / pageSize.value),\n);\n\nconst paginatedData = computed(() => {\n const start = (currentExcelPage.value - 1) * pageSize.value;\n return currentData.value.slice(start, start + pageSize.value);\n});\n\n/* ==================== 方法 ==================== */\nconst handlePageSizeChange = (newPageSize: number) => {\n pageSize.value = newPageSize;\n currentExcelPage.value = 1;\n};\n\nconst syncSheetData = (sheetName: string) => {\n const sheet = props.sheets.find((s) => s.name === sheetName);\n if (sheet) {\n currentData.value = sheet.data;\n currentColumns.value = sheet.columns;\n currentExcelPage.value = 1;\n }\n};\n\n/* ==================== 监听器 ==================== */\nwatch(activeSheet, (newSheet) => {\n syncSheetData(newSheet);\n});\n\n/* sheets 变化时初始化 */\nwatch(\n () => props.sheets,\n (newSheets) => {\n if (newSheets.length > 0) {\n const [firstSheet] = newSheets;\n activeSheet.value = firstSheet.name;\n currentData.value = firstSheet.data;\n currentColumns.value = firstSheet.columns;\n currentExcelPage.value = 1;\n }\n },\n { immediate: true },\n);\n</script>\n\n<style lang=\"scss\" scoped>\n@use \"./index.scss\";\n</style>\n","/**\r\n * useFilePreview — 文件预览核心 composable\r\n * 管理:文件状态、加载、类型检测、下载\r\n */\r\nimport { ref, computed, watch, onUnmounted, type Ref } from \"vue\";\r\nimport {\r\n extractFileNameFromUrl,\r\n getFileType,\r\n getFileConfig,\r\n loadPdf,\r\n loadWord,\r\n loadExcel,\r\n} from \"../data\";\r\nimport type { FilePreviewType, DocHeading, ExcelSheet } from \"../types\";\r\n\r\nexport interface UseFilePreviewOptions {\r\n file: Ref<File | undefined>;\r\n url: Ref<string | undefined>;\r\n fileName: Ref<string>;\r\n}\r\n\r\n/**\r\n * 文件预览核心 composable — 管理文件状态、加载、类型检测、下载\r\n * @param options - 文件源配置(file / url / fileName)\r\n * @param emit - 组件事件发射器\r\n */\r\nexport function useFilePreview(\r\n options: UseFilePreviewOptions,\r\n emit: {\r\n (e: \"preview\", file: File | string): void;\r\n (e: \"download\", file: File | string): void;\r\n },\r\n) {\r\n const { file, url, fileName } = options;\r\n\r\n /* ==================== 基础状态 ==================== */\r\n const loading = ref(false);\r\n const error = ref(\"\");\r\n const fileSize = ref(0);\r\n const showModal = ref(false);\r\n\r\n /* ==================== 解析后的数据 ==================== */\r\n const pdfUrl = ref(\"\");\r\n const pdfTotalPages = ref(0);\r\n\r\n const wordContent = ref(\"\");\r\n const wordHeadings = ref<DocHeading[]>([]);\r\n\r\n const excelSheets = ref<ExcelSheet[]>([]);\r\n\r\n /* ==================== 计算属性 ==================== */\r\n const displayFileName = computed(() => {\r\n if (fileName.value && fileName.value !== \"未知文件\") return fileName.value;\r\n if (file.value?.name) return file.value.name;\r\n if (url.value) return extractFileNameFromUrl(url.value);\r\n return \"未知文件\";\r\n });\r\n\r\n const fileType = computed<FilePreviewType>(() =>\r\n getFileType(displayFileName.value),\r\n );\r\n const fileConfig = computed(() => getFileConfig(fileType.value));\r\n\r\n /* ==================== 内部方法 ==================== */\r\n const clearState = () => {\r\n error.value = \"\";\r\n loading.value = false;\r\n pdfUrl.value = \"\";\r\n pdfTotalPages.value = 0;\r\n wordContent.value = \"\";\r\n wordHeadings.value = [];\r\n excelSheets.value = [];\r\n };\r\n\r\n const setError = (msg: string) => {\r\n error.value = msg;\r\n loading.value = false;\r\n };\r\n\r\n /* ==================== 文件解析 ==================== */\r\n const resolveFile = async (): Promise<File> => {\r\n if (file.value) {\r\n fileSize.value = file.value.size;\r\n return file.value;\r\n }\r\n if (url.value) {\r\n const response = await fetch(url.value);\r\n if (!response.ok)\r\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\r\n\r\n const blob = await response.blob();\r\n const resolved = new File([blob], displayFileName.value, {\r\n type: blob.type,\r\n });\r\n fileSize.value = resolved.size;\r\n return resolved;\r\n }\r\n throw new Error(\"未提供文件或URL\");\r\n };\r\n\r\n const loadByType = async (\r\n currentFile: File,\r\n type: FilePreviewType,\r\n ): Promise<void> => {\r\n switch (type) {\r\n case \"pdf\": {\r\n const result = await loadPdf(currentFile);\r\n pdfUrl.value = result.url;\r\n pdfTotalPages.value = result.totalPages;\r\n break;\r\n }\r\n case \"word\": {\r\n const result = await loadWord(currentFile);\r\n wordContent.value = result.content;\r\n wordHeadings.value = result.headings;\r\n break;\r\n }\r\n case \"excel\": {\r\n const result = await loadExcel(currentFile);\r\n excelSheets.value = result.sheets;\r\n break;\r\n }\r\n default:\r\n throw new Error(\"不支持的文件格式\");\r\n }\r\n };\r\n\r\n /* ==================== 核心方法 ==================== */\r\n const loadFile = async () => {\r\n if (!file.value && !url.value) {\r\n setError(\"未提供文件或URL\");\r\n return;\r\n }\r\n\r\n clearState();\r\n loading.value = true;\r\n\r\n try {\r\n const currentFile = await resolveFile();\r\n await loadByType(currentFile, fileType.value);\r\n loading.value = false;\r\n } catch (err) {\r\n const errorMessage = err instanceof Error ? err.message : \"未知错误\";\r\n setError(`${fileType.value.toUpperCase()}文件加载失败: ${errorMessage}`);\r\n }\r\n };\r\n\r\n const openPreview = async () => {\r\n showModal.value = true;\r\n await loadFile();\r\n emit(\"preview\", file.value || url.value!);\r\n };\r\n\r\n const downloadFile = () => {\r\n if (file.value) {\r\n const downloadUrl = URL.createObjectURL(file.value);\r\n const a = Object.assign(document.createElement(\"a\"), {\r\n href: downloadUrl,\r\n download: displayFileName.value,\r\n });\r\n a.click();\r\n URL.revokeObjectURL(downloadUrl);\r\n } else if (url.value) {\r\n window.open(url.value, \"_blank\");\r\n }\r\n emit(\"download\", file.value || url.value!);\r\n };\r\n\r\n /* ==================== 副作用 ==================== */\r\n watch(\r\n () => file.value?.size,\r\n (newSize) => {\r\n fileSize.value = newSize || 0;\r\n },\r\n { immediate: true },\r\n );\r\n\r\n onUnmounted(() => {\r\n if (pdfUrl.value?.startsWith(\"blob:\")) {\r\n URL.revokeObjectURL(pdfUrl.value.split(\"#\")[0]);\r\n }\r\n });\r\n\r\n return {\r\n /* 状态 */\r\n loading,\r\n error,\r\n fileSize,\r\n showModal,\r\n /* 解析数据 */\r\n pdfUrl,\r\n pdfTotalPages,\r\n wordContent,\r\n wordHeadings,\r\n excelSheets,\r\n /* 计算属性 */\r\n displayFileName,\r\n fileType,\r\n fileConfig,\r\n /* 方法 */\r\n loadFile,\r\n openPreview,\r\n downloadFile,\r\n };\r\n}\r\n","/**\r\n * useFullscreen — 全屏切换 composable\r\n */\r\nimport { ref, onMounted, onUnmounted, type Ref } from \"vue\";\r\nimport { FULLSCREEN_EVENTS } from \"../data\";\r\n\r\n/**\r\n * 全屏切换 composable — 管理全屏状态与跨浏览器兼容\r\n * @param containerRef - 需要全屏的容器元素引用\r\n */\r\nexport function useFullscreen(containerRef: Ref<HTMLElement | undefined>) {\r\n const isFullscreen = ref(false);\r\n\r\n const handleFullscreenChange = () => {\r\n isFullscreen.value = !!document.fullscreenElement;\r\n };\r\n\r\n const tryMethods = (\r\n methods: Array<() => Promise<void>>,\r\n index = 0,\r\n ): Promise<void> => {\r\n if (index >= methods.length) {\r\n console.warn(\"无法切换全屏状态\");\r\n return Promise.resolve();\r\n }\r\n return methods[index]().catch(() => tryMethods(methods, index + 1));\r\n };\r\n\r\n const toggleFullscreen = async () => {\r\n const element = containerRef.value;\r\n if (!element) return;\r\n\r\n const isCurrentlyFullscreen = !!document.fullscreenElement;\r\n\r\n const methods = isCurrentlyFullscreen\r\n ? [\r\n () => document.exitFullscreen(),\r\n () => (document as any).webkitExitFullscreen(),\r\n () => (document as any).mozCancelFullScreen(),\r\n () => (document as any).msExitFullscreen(),\r\n ]\r\n : [\r\n () => element.requestFullscreen(),\r\n () => (element as any).webkitRequestFullscreen(),\r\n () => (element as any).mozRequestFullScreen(),\r\n () => (element as any).msRequestFullscreen(),\r\n ];\r\n\r\n await tryMethods(methods);\r\n };\r\n\r\n const exitFullscreen = async () => {\r\n if (document.fullscreenElement) {\r\n try {\r\n await document.exitFullscreen();\r\n } catch {\r\n /* ignore */\r\n }\r\n }\r\n isFullscreen.value = false;\r\n };\r\n\r\n onMounted(() => {\r\n FULLSCREEN_EVENTS.forEach((event) =>\r\n document.addEventListener(event, handleFullscreenChange),\r\n );\r\n });\r\n\r\n onUnmounted(() => {\r\n FULLSCREEN_EVENTS.forEach((event) =>\r\n document.removeEventListener(event, handleFullscreenChange),\r\n );\r\n });\r\n\r\n return { isFullscreen, toggleFullscreen, exitFullscreen };\r\n}\r\n","<!--\n * @Author: ChenYu ycyplus@gmail.com\n * @Date: 2025-07-01\n * @Description: 文件预览组件(PDF/Word/Excel)\n * @Migration: naive-ui-components 组件库迁移版本\n * Copyright (c) 2025 by CHENY, All Rights Reserved.\n-->\n\n<template>\n <div class=\"c-file-preview-wrapper\">\n <!-- 文件信息卡片模式 -->\n <div\n v-if=\"!autoPreview\"\n class=\"file-info-card\"\n >\n <div class=\"file-info\">\n <div class=\"file-icon\">\n <C_Icon\n :name=\"fileConfig.icon\"\n :size=\"40\"\n :color=\"fileConfig.color\"\n />\n </div>\n\n <div class=\"file-details\">\n <div class=\"file-name\">\n <NEllipsis style=\"max-width: 250px\">{{\n displayFileName\n }}</NEllipsis>\n <NTag\n :type=\"fileConfig.tagType as any\"\n size=\"small\"\n >\n {{ fileType.toUpperCase() }}\n </NTag>\n </div>\n\n <div class=\"file-meta\">\n <span class=\"file-size\">{{ formatFileSize(fileSize) }}</span>\n </div>\n </div>\n\n <div class=\"file-actions\">\n <NButton\n type=\"primary\"\n @click=\"openPreview\"\n >\n <template #icon>\n <C_Icon name=\"ic:outline-visibility\" />\n </template>\n 预览\n </NButton>\n\n <NButton\n type=\"tertiary\"\n @click=\"downloadFile\"\n >\n <template #icon>\n <C_Icon name=\"ic:outline-download\" />\n </template>\n 下载\n </NButton>\n </div>\n </div>\n </div>\n\n <!-- 模态框预览 -->\n <NModal\n v-model:show=\"showModal\"\n :mask-closable=\"false\"\n :closable=\"false\"\n :auto-focus=\"false\"\n transform-origin=\"center\"\n style=\"\n width: 85vw;\n max-width: 1200px;\n min-width: 800px;\n height: 75vh;\n max-height: 700px;\n min-height: 500px;\n \"\n >\n <div\n ref=\"modalContainer\"\n class=\"modal-container\"\n >\n <!-- 自定义头部 -->\n <div class=\"modal-header\">\n <div class=\"modal-title\">\n <C_Icon\n :name=\"fileConfig.icon\"\n :size=\"20\"\n :color=\"fileConfig.color\"\n />\n <span>{{ displayFileName }}</span>\n </div>\n <div class=\"modal-actions\">\n <NButton\n size=\"small\"\n type=\"tertiary\"\n @click=\"downloadFile\"\n >\n <template #icon>\n <C_Icon name=\"ic:outline-download\" />\n </template>\n 下载\n </NButton>\n <NButton\n size=\"small\"\n type=\"tertiary\"\n @click=\"showModal = false\"\n >\n <template #icon>\n <C_Icon name=\"ic:outline-close\" />\n </template>\n </NButton>\n </div>\n </div>\n\n <!-- 预览内容 -->\n <div class=\"modal-content\">\n <!-- 文件信息头部 -->\n <div class=\"preview-header\">\n <div class=\"flex justify-between items-center\">\n <div class=\"flex items-center gap-3\">\n <NTag\n :type=\"fileConfig.tagType as any\"\n size=\"small\"\n >\n <template #icon>\n <C_Icon :name=\"fileConfig.icon\" />\n </template>\n {{ fileType.toUpperCase() }}\n </NTag>\n <NEllipsis style=\"max-width: 300px\">{{\n displayFileName\n }}</NEllipsis>\n <span class=\"text-sm text-gray-500\">{{\n formatFileSize(fileSize)\n }}</span>\n </div>\n\n <div class=\"flex gap-2\">\n <NButton\n size=\"small\"\n type=\"tertiary\"\n :disabled=\"loading\"\n @click=\"loadFile\"\n >\n <template #icon>\n <C_Icon name=\"ic:outline-refresh\" />\n </template>\n 刷新\n </NButton>\n <NButton\n size=\"small\"\n type=\"primary\"\n @click=\"toggleFullscreen\"\n >\n <template #icon>\n <C_Icon\n :name=\"\n isFullscreen\n ? 'ic:outline-fullscreen-exit'\n : 'ic:outline-fullscreen'\n \"\n />\n </template>\n {{ isFullscreen ? '退出全屏' : '全屏' }}\n </NButton>\n </div>\n </div>\n </div>\n\n <!-- 预览内容区域 -->\n <div class=\"preview-content\">\n <!-- 加载和错误状态 -->\n <template v-if=\"loading || error\">\n <div class=\"status-container\">\n <NSpin\n v-if=\"loading\"\n size=\"large\"\n >\n <template #description>\n 正在加载{{ fileType.toUpperCase() }}文件...\n </template>\n </NSpin>\n <NResult\n v-else\n status=\"error\"\n title=\"预览失败\"\n :description=\"error\"\n >\n <template #footer>\n <NButton @click=\"loadFile\">重试</NButton>\n </template>\n </NResult>\n </div>\n </template>\n\n <!-- 文件预览 — 委托给子组件 -->\n <template v-else>\n <PdfViewer\n v-if=\"fileType === 'pdf'\"\n :pdf-url=\"pdfUrl\"\n :total-pages=\"pdfTotalPages\"\n />\n\n <WordViewer\n v-else-if=\"fileType === 'word'\"\n :content=\"wordContent\"\n :headings=\"wordHeadings\"\n />\n\n <ExcelViewer\n v-else-if=\"fileType === 'excel'\"\n :sheets=\"excelSheets\"\n @reload=\"loadFile\"\n />\n\n <!-- 不支持的文件类型 -->\n <NResult\n v-else\n status=\"warning\"\n title=\"不支持的文件格式\"\n :description=\"`暂不支持预览 ${fileType.toUpperCase()} 格式文件`\"\n />\n </template>\n </div>\n </div>\n </div>\n </NModal>\n </div>\n</template>\n\n<script setup lang=\"ts\">\n import { ref, toRefs, watch } from 'vue'\n import { NButton, NEllipsis, NTag, NModal, NSpin, NResult } from 'naive-ui'\n import { formatFileSize } from './data'\n import PdfViewer from './components/PdfViewer/index.vue'\n import WordViewer from './components/WordViewer/index.vue'\n import ExcelViewer from './components/ExcelViewer/index.vue'\n import { useFilePreview } from './composables/useFilePreview'\n import { useFullscreen } from './composables/useFullscreen'\n\n defineOptions({ name: 'C_FilePreview' })\n\n const props = withDefaults(\n defineProps<{\n file?: File\n url?: string\n fileName?: string\n autoPreview?: boolean\n }>(),\n {\n fileName: '未知文件',\n autoPreview: false,\n }\n )\n\n const { file, url, fileName: propFileName, autoPreview } = toRefs(props)\n\n const emit = defineEmits<{\n preview: [file: File | string]\n download: [file: File | string]\n }>()\n\n /* ==================== Composables ==================== */\n const {\n loading,\n error,\n fileSize,\n showModal,\n pdfUrl,\n pdfTotalPages,\n wordContent,\n wordHeadings,\n excelSheets,\n displayFileName,\n fileType,\n fileConfig,\n loadFile,\n openPreview,\n downloadFile,\n } = useFilePreview({ file, url, fileName: propFileName }, emit)\n\n const modalContainer = ref<HTMLElement>()\n const { isFullscreen, toggleFullscreen, exitFullscreen } =\n useFullscreen(modalContainer)\n\n /* ==================== Modal 关闭时退出全屏 ==================== */\n watch(showModal, isShow => {\n if (!isShow) exitFullscreen()\n })\n</script>\n\n<style lang=\"scss\" scoped>\n @use './index.scss';\n</style>\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{t as e}from"./C_Icon2.js";import{t}from"./export-helper.js";import{NButton as n,NDivider as r,NEllipsis as i,NEmpty as a,NInputNumber as o,NModal as s,NPagination as c,NResult as l,NSpin as u,NTabPane as d,NTabs as f,NTag as p,NText as m}from"naive-ui";import{Fragment as h,computed as g,createBlock as _,createCommentVNode as v,createElementBlock as y,createElementVNode as b,createTextVNode as x,createVNode as S,defineComponent as C,isRef as w,normalizeClass as T,normalizeStyle as E,onMounted as D,onUnmounted as O,openBlock as k,ref as A,renderList as j,toDisplayString as M,toRefs as ee,unref as N,vShow as P,watch as F,withCtx as I,withDirectives as L}from"vue";import*as R from"xlsx";import z from"mammoth";const B={pdf:`pdf`,doc:`word`,docx:`word`,xls:`excel`,xlsx:`excel`},V={pdf:{tagType:`error`,icon:`ic:outline-picture-as-pdf`,color:`#dc2626`},word:{tagType:`info`,icon:`ic:outline-description`,color:`#2563eb`},excel:{tagType:`success`,icon:`ic:outline-grid-on`,color:`#16a34a`},unknown:{tagType:`default`,icon:`ic:outline-insert-drive-file`,color:`#6b7280`}},H={pdf:{min:.5,max:3,step:.25,default:1},word:{min:50,max:200,step:10,default:100}},U=[20,50,100,200],W=[`fullscreenchange`,`webkitfullscreenchange`,`mozfullscreenchange`,`MSFullscreenChange`],G=e=>{try{let t=e.split(`/`).pop()||e.split(`\\`).pop();if(t?.includes(`.`)){let n=decodeURIComponent(t.split(`?`)[0]);if(n&&n!==e)return n}}catch(e){console.warn(`解析URL文件名失败:`,e)}return`未知文件`},K=e=>{if(e===0)return`0 B`;let t=1024,n=[`B`,`KB`,`MB`,`GB`],r=Math.floor(Math.log(e)/Math.log(t));return parseFloat((e/t**+r).toFixed(1))+` `+n[r]},te=e=>{if(!e||e===`未知文件`)return`unknown`;let t=e.toLowerCase().split(`.`).pop();return t&&B[t]||`unknown`},ne=e=>V[e]||V.unknown,q=(e,t)=>n=>{let{min:r,max:i,step:a,default:o}=t;switch(n){case`reset`:e.value=o;break;case`in`:e.value<i&&(e.value+=a);break;case`out`:e.value>r&&(e.value-=a);break}},re=e=>{let t=``;for(;e>=0;)t=String.fromCharCode(65+e%26)+t,e=Math.floor(e/26)-1;return t},J=e=>{if(!e)return``;let t=String(e).trim();if(!isNaN(Number(t))&&t!==``&&t.length<15){let e=Number(t);return Number.isInteger(e)?e.toLocaleString():e.toLocaleString(void 0,{maximumFractionDigits:2})}return t},Y=e=>{if(!e)return`cell-empty`;let t=String(e).trim();return!isNaN(Number(t))&&t!==``?`cell-number`:t.match(/[■▬▪▫─━]/)?`cell-gantt`:t.match(/^\d{4}[-/]\d{2}[-/]\d{2}/)||t.match(/^\d{2}[-/]\d{2}[-/]\d{4}/)?`cell-date`:[`true`,`false`].includes(t.toLowerCase())?`cell-boolean`:t.length>20?`cell-text cell-long`:`cell-text`},X=(e,t)=>{let{c:n,r}=R.utils.decode_range(e[`!ref`]||`A1:A1`).e,i=Array.from({length:n+1},(t,n)=>{let r=e[R.utils.encode_cell({r:0,c:n})],i=r?String(r.v||``).trim():`列${n+1}`;return{title:i||`列${n+1}`,key:`col_${n}`,width:Math.min(Math.max(i.length*12,80),200)}}),a=new Map;return t.forEach(({s:{r:e,c:t},e:{r:n,c:r}})=>{for(let i=e;i<=n;i++)for(let o=t;o<=r;o++)a.set(`${i}-${o}`,{isMain:i===e&&o===t,rowspan:n-e+1,colspan:r-t+1})}),{data:Array.from({length:r+1},(t,r)=>{let i={};for(let t=0;t<=n;t++){let n=e[R.utils.encode_cell({r,c:t})],o=a.get(`${r}-${t}`);i[`col_${t}`]={value:n&&n.v||``,merged:!!o,hidden:o&&!o.isMain,rowspan:o?.isMain?o.rowspan:1,colspan:o?.isMain?o.colspan:1}}return i}),columns:i}};async function ie(e){return{url:URL.createObjectURL(e)+`#toolbar=1&navpanes=1&scrollbar=1&view=FitH`,totalPages:1}}async function ae(e){let t=await e.arrayBuffer(),n=(await z.convertToHtml({arrayBuffer:t,styleMap:[`p[style-name='Heading 1'] => h1:fresh`,`p[style-name='Heading 2'] => h2:fresh`,`p[style-name='Heading 3'] => h3:fresh`,`p[style-name='Title'] => h1.title:fresh`]})).value,r=[],i=document.createElement(`div`);i.innerHTML=n;let a=i.querySelectorAll(`h1, h2, h3, h4, h5, h6`);return Array.from(a).forEach((e,t)=>{let i=`heading-${t}`,a=parseInt(e.tagName.charAt(1)),o=e.textContent||``;n=n.replace(e.outerHTML,e.outerHTML.replace(e.tagName.toLowerCase(),`${e.tagName.toLowerCase()} id="${i}"`)),r.push({id:i,text:o,level:a})}),{content:n,headings:r}}async function oe(e){let t=await e.arrayBuffer(),n=R.read(t,{type:`array`,cellStyles:!0,cellFormula:!0,cellDates:!0});if(!n.SheetNames.length)throw Error(`Excel文件中没有找到工作表`);return{sheets:n.SheetNames.map(e=>{let t=n.Sheets[e],r=t[`!merges`]||[],{data:i,columns:a}=X(t,r);return{name:e,data:i,merges:r,columns:a}})}}const se={class:`file-container pdf-container`},ce={class:`file-toolbar`},le={class:`flex justify-between items-center`},ue={class:`flex gap-2 items-center`},de={class:`text-sm text-gray-600`},fe={class:`flex gap-2 items-center`},pe={class:`text-sm text-gray-600 min-w-12 text-center`},me={class:`file-viewer`},he=[`src`];var ge=t(C({__name:`index`,props:{pdfUrl:{},totalPages:{}},setup(t){let r=t,i=A(1),a=A(1),s=q(a,H.pdf),c=e=>{if(typeof e==`number`)i.value=Math.max(1,Math.min(e,r.totalPages));else{let t=e===`prev`?-1:1;i.value=Math.max(1,Math.min(i.value+t,r.totalPages))}};return(t,r)=>{let l=e;return k(),y(`div`,se,[b(`div`,ce,[b(`div`,le,[v(` 翻页控制 `),b(`div`,ue,[S(N(n),{size:`small`,disabled:i.value<=1,onClick:r[0]||=e=>c(`prev`)},{icon:I(()=>[S(l,{name:`ic:outline-chevron-left`})]),_:1},8,[`disabled`]),S(N(o),{value:i.value,"onUpdate:value":[r[1]||=e=>i.value=e,c],size:`small`,min:1,max:t.totalPages,style:{width:`80px`}},null,8,[`value`,`max`,`onUpdate:value`]),b(`span`,de,`/ `+M(t.totalPages),1),S(N(n),{size:`small`,disabled:i.value>=t.totalPages,onClick:r[2]||=e=>c(`next`)},{icon:I(()=>[S(l,{name:`ic:outline-chevron-right`})]),_:1},8,[`disabled`])]),v(` 缩放控制 `),b(`div`,fe,[S(N(n),{size:`small`,disabled:a.value<=.5,onClick:r[3]||=e=>N(s)(`out`)},{icon:I(()=>[S(l,{name:`ic:outline-zoom-out`})]),_:1},8,[`disabled`]),b(`span`,pe,M(Math.round(a.value*100))+`% `,1),S(N(n),{size:`small`,disabled:a.value>=3,onClick:r[4]||=e=>N(s)(`in`)},{icon:I(()=>[S(l,{name:`ic:outline-zoom-in`})]),_:1},8,[`disabled`]),S(N(n),{size:`small`,onClick:r[5]||=e=>N(s)(`reset`)},{icon:I(()=>[S(l,{name:`ic:outline-fit-screen`})]),default:I(()=>[r[6]||=x(` 适应 `,-1)]),_:1,__:[6]})])])]),b(`div`,me,[t.pdfUrl?(k(),y(`iframe`,{key:0,src:t.pdfUrl,class:`w-full h-full border-0`,title:`PDF预览`,frameborder:`0`,allowfullscreen:``},null,8,he)):v(`v-if`,!0)])])}}}),[[`__scopeId`,`data-v-e96499e0`]]);const _e={class:`file-container word-container`},ve={class:`file-toolbar`},ye={class:`flex gap-2 items-center`},be={class:`text-sm text-gray-600 min-w-12 text-center`},xe={class:`word-layout`},Se={class:`word-main`},Ce={key:0,class:`word-outline`},we={class:`outline-content`},Te=[`onClick`],Ee={class:`word-content`},De=[`innerHTML`];var Oe=t(C({__name:`index`,props:{content:{},headings:{}},setup(t){let i=A(!0),a=A(100),o=q(a,H.word),s=e=>{document.getElementById(e)?.scrollIntoView({behavior:`smooth`,block:`start`})};return(t,c)=>{let l=e;return k(),y(`div`,_e,[b(`div`,ve,[b(`div`,ye,[S(N(n),{size:`small`,onClick:c[0]||=e=>i.value=!i.value},{icon:I(()=>[S(l,{name:`ic:outline-list`})]),default:I(()=>[x(` `+M(i.value?`隐藏`:`显示`)+`目录 `,1)]),_:1}),S(N(r),{vertical:``}),S(N(n),{size:`small`,disabled:a.value<=50,onClick:c[1]||=e=>N(o)(`out`)},{icon:I(()=>[S(l,{name:`ic:outline-zoom-out`})]),_:1},8,[`disabled`]),b(`span`,be,M(a.value)+`% `,1),S(N(n),{size:`small`,disabled:a.value>=200,onClick:c[2]||=e=>N(o)(`in`)},{icon:I(()=>[S(l,{name:`ic:outline-zoom-in`})]),_:1},8,[`disabled`]),S(N(n),{size:`small`,onClick:c[3]||=e=>N(o)(`reset`)},{icon:I(()=>[S(l,{name:`ic:outline-fit-screen`})]),default:I(()=>[c[4]||=x(` 重置 `,-1)]),_:1,__:[4]})])]),b(`div`,xe,[b(`div`,Se,[v(` 侧边栏目录 `),i.value?(k(),y(`div`,Ce,[c[5]||=b(`div`,{class:`outline-header`},[b(`h3`,{class:`text-sm font-semibold`},`文档目录`)],-1),b(`div`,we,[(k(!0),y(h,null,j(t.headings,(e,t)=>(k(),y(`div`,{key:t,class:T([`outline-item`,`level-${e.level}`]),onClick:t=>s(e.id)},M(e.text),11,Te))),128))])])):v(`v-if`,!0),v(` 主要内容区域 `),b(`div`,Ee,[b(`div`,{class:`word-document`,style:E({transform:`scale(${a.value/100})`,transformOrigin:`top center`}),innerHTML:t.content},null,12,De)])])])])}}}),[[`__scopeId`,`data-v-42ca58ad`]]);const ke={class:`file-container excel-container`},Ae={class:`file-toolbar`},je={class:`flex justify-between items-center`},Me={class:`flex gap-2 items-center`},Ne={key:1,class:`text-sm text-gray-600`},Pe={class:`flex gap-2 items-center`},Fe={class:`excel-viewer`},Ie={key:0,class:`excel-info`},Le={class:`excel-table-container`},Re={key:0,class:`excel-table`},ze={class:`header-content`},Be={class:`column-letter`},Ve={class:`column-title`},He={class:`row-number`},Ue=[`rowspan`,`colspan`,`title`],We={key:1,class:`excel-empty`},Ge={key:0,class:`excel-pagination`};var Ke=t(C({__name:`index`,props:{sheets:{}},emits:[`reload`],setup(t){let r=t,i=A(``),o=A(!1),s=A(1),l=A(50),u=A([]),p=A([]),C=g(()=>Math.ceil(u.value.length/l.value)),w=g(()=>{let e=(s.value-1)*l.value;return u.value.slice(e,e+l.value)}),D=e=>{l.value=e,s.value=1},O=e=>{let t=r.sheets.find(t=>t.name===e);t&&(u.value=t.data,p.value=t.columns,s.value=1)};return F(i,e=>{O(e)}),F(()=>r.sheets,e=>{if(e.length>0){let[t]=e;i.value=t.name,u.value=t.data,p.value=t.columns,s.value=1}},{immediate:!0}),(t,r)=>{let g=e;return k(),y(`div`,ke,[v(` 工具栏 `),b(`div`,Ae,[b(`div`,je,[b(`div`,Me,[t.sheets.length>1?(k(),_(N(f),{key:0,value:i.value,"onUpdate:value":r[0]||=e=>i.value=e,type:`card`,size:`small`},{default:I(()=>[(k(!0),y(h,null,j(t.sheets,e=>(k(),_(N(d),{key:e.name,name:e.name,tab:e.name},null,8,[`name`,`tab`]))),128))]),_:1},8,[`value`])):(k(),y(`span`,Ne,` 工作表: `+M(i.value),1))]),b(`div`,Pe,[S(N(n),{size:`small`,onClick:r[1]||=e=>o.value=!o.value},{icon:I(()=>[S(g,{name:`ic:outline-format-paint`})]),default:I(()=>[x(` `+M(o.value?`紧凑视图`:`完整格式`),1)]),_:1})])])]),b(`div`,Fe,[v(` 信息面板 `),u.value.length>0?(k(),y(`div`,Ie,[S(N(m),{depth:`3`,class:`text-sm`},{default:I(()=>[x(` 当前工作表: `+M(i.value)+` | 总行数: `+M(u.value.length)+` | 总列数: `+M(p.value.length)+` | 当前页: `+M(s.value)+`/`+M(C.value),1)]),_:1})])):v(`v-if`,!0),v(` 表格 `),b(`div`,Le,[b(`div`,{class:T([`excel-table-wrapper`,{"simple-mode":!o.value}])},[u.value.length>0?(k(),y(`table`,Re,[b(`thead`,null,[b(`tr`,null,[r[4]||=b(`th`,{class:`row-number`},`行号`,-1),(k(!0),y(h,null,j(p.value,(e,t)=>(k(),y(`th`,{key:e.key,class:`excel-header`,style:E({minWidth:e.width+`px`})},[b(`div`,ze,[b(`span`,Be,M(N(re)(t)),1),b(`span`,Ve,M(e.title),1)])],4))),128))])]),b(`tbody`,null,[(k(!0),y(h,null,j(w.value,(e,t)=>(k(),y(`tr`,{key:t,class:`excel-row`},[b(`td`,He,M((s.value-1)*l.value+t+1),1),(k(!0),y(h,null,j(p.value,t=>L((k(),y(`td`,{key:t.key,class:T([`excel-cell`,[N(Y)(e[t.key]?.value),e[t.key]?.merged?`merged-cell`:``,o.value?``:`compact-cell`]]),rowspan:e[t.key]?.rowspan||1,colspan:e[t.key]?.colspan||1,title:e[t.key]?.value},M(N(J)(e[t.key]?.value)),11,Ue)),[[P,!e[t.key]?.hidden]])),128))]))),128))])])):(k(),y(`div`,We,[S(N(a),{description:`该工作表没有数据或解析失败`},{extra:I(()=>[S(N(n),{size:`small`,onClick:r[2]||=e=>t.$emit(`reload`)},{default:I(()=>r[5]||=[x(` 重新解析 `,-1)]),_:1,__:[5]})]),_:1})]))],2),v(` 分页 `),C.value>1?(k(),y(`div`,Ge,[S(N(c),{page:s.value,"onUpdate:page":r[3]||=e=>s.value=e,"page-count":C.value,"page-size":l.value,"show-size-picker":``,"page-sizes":N(U),"onUpdate:pageSize":D},null,8,[`page`,`page-count`,`page-size`,`page-sizes`])])):v(`v-if`,!0)])])])}}}),[[`__scopeId`,`data-v-b6c3e1b9`]]);function Z(e,t){let{file:n,url:r,fileName:i}=e,a=A(!1),o=A(``),s=A(0),c=A(!1),l=A(``),u=A(0),d=A(``),f=A([]),p=A([]),m=g(()=>i.value&&i.value!==`未知文件`?i.value:n.value?.name?n.value.name:r.value?G(r.value):`未知文件`),h=g(()=>te(m.value)),_=g(()=>ne(h.value)),v=()=>{o.value=``,a.value=!1,l.value=``,u.value=0,d.value=``,f.value=[],p.value=[]},y=e=>{o.value=e,a.value=!1},b=async()=>{if(n.value)return s.value=n.value.size,n.value;if(r.value){let e=await fetch(r.value);if(!e.ok)throw Error(`HTTP ${e.status}: ${e.statusText}`);let t=await e.blob(),n=new File([t],m.value,{type:t.type});return s.value=n.size,n}throw Error(`未提供文件或URL`)},x=async(e,t)=>{switch(t){case`pdf`:{let t=await ie(e);l.value=t.url,u.value=t.totalPages;break}case`word`:{let t=await ae(e);d.value=t.content,f.value=t.headings;break}case`excel`:p.value=(await oe(e)).sheets;break;default:throw Error(`不支持的文件格式`)}},S=async()=>{if(!n.value&&!r.value){y(`未提供文件或URL`);return}v(),a.value=!0;try{await x(await b(),h.value),a.value=!1}catch(e){let t=e instanceof Error?e.message:`未知错误`;y(`${h.value.toUpperCase()}文件加载失败: ${t}`)}};return F(()=>n.value?.size,e=>{s.value=e||0},{immediate:!0}),O(()=>{l.value?.startsWith(`blob:`)&&URL.revokeObjectURL(l.value.split(`#`)[0])}),{loading:a,error:o,fileSize:s,showModal:c,pdfUrl:l,pdfTotalPages:u,wordContent:d,wordHeadings:f,excelSheets:p,displayFileName:m,fileType:h,fileConfig:_,loadFile:S,openPreview:async()=>{c.value=!0,await S(),t(`preview`,n.value||r.value)},downloadFile:()=>{if(n.value){let e=URL.createObjectURL(n.value);Object.assign(document.createElement(`a`),{href:e,download:m.value}).click(),URL.revokeObjectURL(e)}else r.value&&window.open(r.value,`_blank`);t(`download`,n.value||r.value)}}}function Q(e){let t=A(!1),n=()=>{t.value=!!document.fullscreenElement},r=(e,t=0)=>t>=e.length?(console.warn(`无法切换全屏状态`),Promise.resolve()):e[t]().catch(()=>r(e,t+1));return D(()=>{W.forEach(e=>document.addEventListener(e,n))}),O(()=>{W.forEach(e=>document.removeEventListener(e,n))}),{isFullscreen:t,toggleFullscreen:async()=>{let t=e.value;t&&await r(document.fullscreenElement?[()=>document.exitFullscreen(),()=>document.webkitExitFullscreen(),()=>document.mozCancelFullScreen(),()=>document.msExitFullscreen()]:[()=>t.requestFullscreen(),()=>t.webkitRequestFullscreen(),()=>t.mozRequestFullScreen(),()=>t.msRequestFullscreen()])},exitFullscreen:async()=>{if(document.fullscreenElement)try{await document.exitFullscreen()}catch{}t.value=!1}}}const qe={class:`c-file-preview-wrapper`},Je={key:0,class:`file-info-card`},Ye={class:`file-info`},Xe={class:`file-icon`},Ze={class:`file-details`},Qe={class:`file-name`},$e={class:`file-meta`},et={class:`file-size`},tt={class:`file-actions`},$={class:`modal-header`},nt={class:`modal-title`},rt={class:`modal-actions`},it={class:`modal-content`},at={class:`preview-header`},ot={class:`flex justify-between items-center`},st={class:`flex items-center gap-3`},ct={class:`text-sm text-gray-500`},lt={class:`flex gap-2`},ut={class:`preview-content`},dt={key:0,class:`status-container`};var ft=t(C({name:`C_FilePreview`,__name:`index`,props:{file:{},url:{},fileName:{default:`未知文件`},autoPreview:{type:Boolean,default:!1}},emits:[`preview`,`download`],setup(t,{emit:r}){let{file:a,url:o,fileName:c,autoPreview:d}=ee(t),{loading:f,error:m,fileSize:g,showModal:C,pdfUrl:T,pdfTotalPages:E,wordContent:D,wordHeadings:O,excelSheets:j,displayFileName:P,fileType:L,fileConfig:R,loadFile:z,openPreview:B,downloadFile:V}=Z({file:a,url:o,fileName:c},r),H=A(),{isFullscreen:U,toggleFullscreen:W,exitFullscreen:G}=Q(H);return F(C,e=>{e||G()}),(t,r)=>{let a=e;return k(),y(`div`,qe,[v(` 文件信息卡片模式 `),N(d)?v(`v-if`,!0):(k(),y(`div`,Je,[b(`div`,Ye,[b(`div`,Xe,[S(a,{name:N(R).icon,size:40,color:N(R).color},null,8,[`name`,`color`])]),b(`div`,Ze,[b(`div`,Qe,[S(N(i),{style:{"max-width":`250px`}},{default:I(()=>[x(M(N(P)),1)]),_:1}),S(N(p),{type:N(R).tagType,size:`small`},{default:I(()=>[x(M(N(L).toUpperCase()),1)]),_:1},8,[`type`])]),b(`div`,$e,[b(`span`,et,M(N(K)(N(g))),1)])]),b(`div`,tt,[S(N(n),{type:`primary`,onClick:N(B)},{icon:I(()=>[S(a,{name:`ic:outline-visibility`})]),default:I(()=>[r[2]||=x(` 预览 `,-1)]),_:1,__:[2]},8,[`onClick`]),S(N(n),{type:`tertiary`,onClick:N(V)},{icon:I(()=>[S(a,{name:`ic:outline-download`})]),default:I(()=>[r[3]||=x(` 下载 `,-1)]),_:1,__:[3]},8,[`onClick`])])])])),v(` 模态框预览 `),S(N(s),{show:N(C),"onUpdate:show":r[1]||=e=>w(C)?C.value=e:null,"mask-closable":!1,closable:!1,"auto-focus":!1,"transform-origin":`center`,style:{width:`85vw`,"max-width":`1200px`,"min-width":`800px`,height:`75vh`,"max-height":`700px`,"min-height":`500px`}},{default:I(()=>[b(`div`,{ref_key:`modalContainer`,ref:H,class:`modal-container`},[v(` 自定义头部 `),b(`div`,$,[b(`div`,nt,[S(a,{name:N(R).icon,size:20,color:N(R).color},null,8,[`name`,`color`]),b(`span`,null,M(N(P)),1)]),b(`div`,rt,[S(N(n),{size:`small`,type:`tertiary`,onClick:N(V)},{icon:I(()=>[S(a,{name:`ic:outline-download`})]),default:I(()=>[r[4]||=x(` 下载 `,-1)]),_:1,__:[4]},8,[`onClick`]),S(N(n),{size:`small`,type:`tertiary`,onClick:r[0]||=e=>C.value=!1},{icon:I(()=>[S(a,{name:`ic:outline-close`})]),_:1})])]),v(` 预览内容 `),b(`div`,it,[v(` 文件信息头部 `),b(`div`,at,[b(`div`,ot,[b(`div`,st,[S(N(p),{type:N(R).tagType,size:`small`},{icon:I(()=>[S(a,{name:N(R).icon},null,8,[`name`])]),default:I(()=>[x(` `+M(N(L).toUpperCase()),1)]),_:1},8,[`type`]),S(N(i),{style:{"max-width":`300px`}},{default:I(()=>[x(M(N(P)),1)]),_:1}),b(`span`,ct,M(N(K)(N(g))),1)]),b(`div`,lt,[S(N(n),{size:`small`,type:`tertiary`,disabled:N(f),onClick:N(z)},{icon:I(()=>[S(a,{name:`ic:outline-refresh`})]),default:I(()=>[r[5]||=x(` 刷新 `,-1)]),_:1,__:[5]},8,[`disabled`,`onClick`]),S(N(n),{size:`small`,type:`primary`,onClick:N(W)},{icon:I(()=>[S(a,{name:N(U)?`ic:outline-fullscreen-exit`:`ic:outline-fullscreen`},null,8,[`name`])]),default:I(()=>[x(` `+M(N(U)?`退出全屏`:`全屏`),1)]),_:1},8,[`onClick`])])])]),v(` 预览内容区域 `),b(`div`,ut,[v(` 加载和错误状态 `),N(f)||N(m)?(k(),y(`div`,dt,[N(f)?(k(),_(N(u),{key:0,size:`large`},{description:I(()=>[x(` 正在加载`+M(N(L).toUpperCase())+`文件... `,1)]),_:1})):(k(),_(N(l),{key:1,status:`error`,title:`预览失败`,description:N(m)},{footer:I(()=>[S(N(n),{onClick:N(z)},{default:I(()=>r[6]||=[x(`重试`,-1)]),_:1,__:[6]},8,[`onClick`])]),_:1},8,[`description`]))])):(k(),y(h,{key:1},[v(` 文件预览 — 委托给子组件 `),N(L)===`pdf`?(k(),_(ge,{key:0,"pdf-url":N(T),"total-pages":N(E)},null,8,[`pdf-url`,`total-pages`])):N(L)===`word`?(k(),_(Oe,{key:1,content:N(D),headings:N(O)},null,8,[`content`,`headings`])):N(L)===`excel`?(k(),_(Ke,{key:2,sheets:N(j),onReload:N(z)},null,8,[`sheets`,`onReload`])):(k(),y(h,{key:3},[v(` 不支持的文件类型 `),S(N(l),{status:`warning`,title:`不支持的文件格式`,description:`暂不支持预览 ${N(L).toUpperCase()} 格式文件`},null,8,[`description`])],2112))],64))])])],512)]),_:1},8,[`show`])])}}}),[[`__scopeId`,`data-v-1037e17e`]]);export{Q as n,Z as r,ft as t};
1
+ import{t as e}from"./export-helper.js";import{Fragment as t,computed as n,createBlock as r,createCommentVNode as i,createElementBlock as a,createElementVNode as o,createTextVNode as s,createVNode as c,defineComponent as l,isRef as u,normalizeClass as d,normalizeStyle as f,onMounted as p,onUnmounted as m,openBlock as h,ref as g,renderList as _,resolveComponent as v,toDisplayString as y,toRefs as b,unref as x,vShow as S,watch as C,withCtx as w,withDirectives as T}from"vue";import{NButton as E,NDivider as D,NEllipsis as O,NEmpty as k,NInputNumber as A,NModal as j,NPagination as M,NResult as N,NSpin as P,NTabPane as F,NTabs as I,NTag as L,NText as R}from"naive-ui";import*as z from"xlsx";import B from"mammoth";const V={pdf:`pdf`,doc:`word`,docx:`word`,xls:`excel`,xlsx:`excel`},H={pdf:{tagType:`error`,icon:`ic:outline-picture-as-pdf`,color:`#dc2626`},word:{tagType:`info`,icon:`ic:outline-description`,color:`#2563eb`},excel:{tagType:`success`,icon:`ic:outline-grid-on`,color:`#16a34a`},unknown:{tagType:`default`,icon:`ic:outline-insert-drive-file`,color:`#6b7280`}},U={pdf:{min:.5,max:3,step:.25,default:1},word:{min:50,max:200,step:10,default:100}},W=[20,50,100,200],G=[`fullscreenchange`,`webkitfullscreenchange`,`mozfullscreenchange`,`MSFullscreenChange`],K=e=>{try{let t=e.split(`/`).pop()||e.split(`\\`).pop();if(t?.includes(`.`)){let n=decodeURIComponent(t.split(`?`)[0]);if(n&&n!==e)return n}}catch(e){console.warn(`解析URL文件名失败:`,e)}return`未知文件`},q=e=>{if(e===0)return`0 B`;let t=1024,n=[`B`,`KB`,`MB`,`GB`],r=Math.floor(Math.log(e)/Math.log(t));return parseFloat((e/t**+r).toFixed(1))+` `+n[r]},ee=e=>{if(!e||e===`未知文件`)return`unknown`;let t=e.toLowerCase().split(`.`).pop();return t&&V[t]||`unknown`},te=e=>H[e]||H.unknown,J=(e,t)=>n=>{let{min:r,max:i,step:a,default:o}=t;switch(n){case`reset`:e.value=o;break;case`in`:e.value<i&&(e.value+=a);break;case`out`:e.value>r&&(e.value-=a);break}},ne=e=>{let t=``;for(;e>=0;)t=String.fromCharCode(65+e%26)+t,e=Math.floor(e/26)-1;return t},re=e=>{if(!e)return``;let t=String(e).trim();if(!isNaN(Number(t))&&t!==``&&t.length<15){let e=Number(t);return Number.isInteger(e)?e.toLocaleString():e.toLocaleString(void 0,{maximumFractionDigits:2})}return t},Y=e=>{if(!e)return`cell-empty`;let t=String(e).trim();return!isNaN(Number(t))&&t!==``?`cell-number`:t.match(/[■▬▪▫─━]/)?`cell-gantt`:t.match(/^\d{4}[-/]\d{2}[-/]\d{2}/)||t.match(/^\d{2}[-/]\d{2}[-/]\d{4}/)?`cell-date`:[`true`,`false`].includes(t.toLowerCase())?`cell-boolean`:t.length>20?`cell-text cell-long`:`cell-text`},X=(e,t)=>{let{c:n,r}=z.utils.decode_range(e[`!ref`]||`A1:A1`).e,i=Array.from({length:n+1},(t,n)=>{let r=e[z.utils.encode_cell({r:0,c:n})],i=r?String(r.v||``).trim():`列${n+1}`;return{title:i||`列${n+1}`,key:`col_${n}`,width:Math.min(Math.max(i.length*12,80),200)}}),a=new Map;return t.forEach(({s:{r:e,c:t},e:{r:n,c:r}})=>{for(let i=e;i<=n;i++)for(let o=t;o<=r;o++)a.set(`${i}-${o}`,{isMain:i===e&&o===t,rowspan:n-e+1,colspan:r-t+1})}),{data:Array.from({length:r+1},(t,r)=>{let i={};for(let t=0;t<=n;t++){let n=e[z.utils.encode_cell({r,c:t})],o=a.get(`${r}-${t}`);i[`col_${t}`]={value:n&&n.v||``,merged:!!o,hidden:o&&!o.isMain,rowspan:o?.isMain?o.rowspan:1,colspan:o?.isMain?o.colspan:1}}return i}),columns:i}};async function ie(e){return{url:URL.createObjectURL(e)+`#toolbar=1&navpanes=1&scrollbar=1&view=FitH`,totalPages:1}}async function ae(e){let t=await e.arrayBuffer(),n=(await B.convertToHtml({arrayBuffer:t,styleMap:[`p[style-name='Heading 1'] => h1:fresh`,`p[style-name='Heading 2'] => h2:fresh`,`p[style-name='Heading 3'] => h3:fresh`,`p[style-name='Title'] => h1.title:fresh`]})).value,r=[],i=document.createElement(`div`);i.innerHTML=n;let a=i.querySelectorAll(`h1, h2, h3, h4, h5, h6`);return Array.from(a).forEach((e,t)=>{let i=`heading-${t}`,a=parseInt(e.tagName.charAt(1)),o=e.textContent||``;n=n.replace(e.outerHTML,e.outerHTML.replace(e.tagName.toLowerCase(),`${e.tagName.toLowerCase()} id="${i}"`)),r.push({id:i,text:o,level:a})}),{content:n,headings:r}}async function oe(e){let t=await e.arrayBuffer(),n=z.read(t,{type:`array`,cellStyles:!0,cellFormula:!0,cellDates:!0});if(!n.SheetNames.length)throw Error(`Excel文件中没有找到工作表`);return{sheets:n.SheetNames.map(e=>{let t=n.Sheets[e],r=t[`!merges`]||[],{data:i,columns:a}=X(t,r);return{name:e,data:i,merges:r,columns:a}})}}const se={class:`file-container pdf-container`},ce={class:`file-toolbar`},le={class:`flex justify-between items-center`},ue={class:`flex gap-2 items-center`},de={class:`text-sm text-gray-600`},fe={class:`flex gap-2 items-center`},pe={class:`text-sm text-gray-600 min-w-12 text-center`},me={class:`file-viewer`},he=[`src`];var ge=e(l({__name:`index`,props:{pdfUrl:{},totalPages:{}},setup(e){let t=e,n=g(1),r=g(1),l=J(r,U.pdf),u=e=>{if(typeof e==`number`)n.value=Math.max(1,Math.min(e,t.totalPages));else{let r=e===`prev`?-1:1;n.value=Math.max(1,Math.min(n.value+r,t.totalPages))}};return(e,t)=>{let d=v(`C_Icon`);return h(),a(`div`,se,[o(`div`,ce,[o(`div`,le,[i(` 翻页控制 `),o(`div`,ue,[c(x(E),{size:`small`,disabled:n.value<=1,onClick:t[0]||=e=>u(`prev`)},{icon:w(()=>[c(d,{name:`ic:outline-chevron-left`})]),_:1},8,[`disabled`]),c(x(A),{value:n.value,"onUpdate:value":[t[1]||=e=>n.value=e,u],size:`small`,min:1,max:e.totalPages,style:{width:`80px`}},null,8,[`value`,`max`,`onUpdate:value`]),o(`span`,de,`/ `+y(e.totalPages),1),c(x(E),{size:`small`,disabled:n.value>=e.totalPages,onClick:t[2]||=e=>u(`next`)},{icon:w(()=>[c(d,{name:`ic:outline-chevron-right`})]),_:1},8,[`disabled`])]),i(` 缩放控制 `),o(`div`,fe,[c(x(E),{size:`small`,disabled:r.value<=.5,onClick:t[3]||=e=>x(l)(`out`)},{icon:w(()=>[c(d,{name:`ic:outline-zoom-out`})]),_:1},8,[`disabled`]),o(`span`,pe,y(Math.round(r.value*100))+`% `,1),c(x(E),{size:`small`,disabled:r.value>=3,onClick:t[4]||=e=>x(l)(`in`)},{icon:w(()=>[c(d,{name:`ic:outline-zoom-in`})]),_:1},8,[`disabled`]),c(x(E),{size:`small`,onClick:t[5]||=e=>x(l)(`reset`)},{icon:w(()=>[c(d,{name:`ic:outline-fit-screen`})]),default:w(()=>[t[6]||=s(` 适应 `,-1)]),_:1,__:[6]})])])]),o(`div`,me,[e.pdfUrl?(h(),a(`iframe`,{key:0,src:e.pdfUrl,class:`w-full h-full border-0`,title:`PDF预览`,frameborder:`0`,allowfullscreen:``},null,8,he)):i(`v-if`,!0)])])}}}),[[`__scopeId`,`data-v-b3a276cb`]]);const _e={class:`file-container word-container`},ve={class:`file-toolbar`},ye={class:`flex gap-2 items-center`},be={class:`text-sm text-gray-600 min-w-12 text-center`},xe={class:`word-layout`},Se={class:`word-main`},Ce={key:0,class:`word-outline`},we={class:`outline-content`},Te=[`onClick`],Ee={class:`word-content`},De=[`innerHTML`];var Oe=e(l({__name:`index`,props:{content:{},headings:{}},setup(e){let n=g(!0),r=g(100),l=J(r,U.word),u=e=>{document.getElementById(e)?.scrollIntoView({behavior:`smooth`,block:`start`})};return(e,p)=>{let m=v(`C_Icon`);return h(),a(`div`,_e,[o(`div`,ve,[o(`div`,ye,[c(x(E),{size:`small`,onClick:p[0]||=e=>n.value=!n.value},{icon:w(()=>[c(m,{name:`ic:outline-list`})]),default:w(()=>[s(` `+y(n.value?`隐藏`:`显示`)+`目录 `,1)]),_:1}),c(x(D),{vertical:``}),c(x(E),{size:`small`,disabled:r.value<=50,onClick:p[1]||=e=>x(l)(`out`)},{icon:w(()=>[c(m,{name:`ic:outline-zoom-out`})]),_:1},8,[`disabled`]),o(`span`,be,y(r.value)+`% `,1),c(x(E),{size:`small`,disabled:r.value>=200,onClick:p[2]||=e=>x(l)(`in`)},{icon:w(()=>[c(m,{name:`ic:outline-zoom-in`})]),_:1},8,[`disabled`]),c(x(E),{size:`small`,onClick:p[3]||=e=>x(l)(`reset`)},{icon:w(()=>[c(m,{name:`ic:outline-fit-screen`})]),default:w(()=>[p[4]||=s(` 重置 `,-1)]),_:1,__:[4]})])]),o(`div`,xe,[o(`div`,Se,[i(` 侧边栏目录 `),n.value?(h(),a(`div`,Ce,[p[5]||=o(`div`,{class:`outline-header`},[o(`h3`,{class:`text-sm font-semibold`},`文档目录`)],-1),o(`div`,we,[(h(!0),a(t,null,_(e.headings,(e,t)=>(h(),a(`div`,{key:t,class:d([`outline-item`,`level-${e.level}`]),onClick:t=>u(e.id)},y(e.text),11,Te))),128))])])):i(`v-if`,!0),i(` 主要内容区域 `),o(`div`,Ee,[o(`div`,{class:`word-document`,style:f({transform:`scale(${r.value/100})`,transformOrigin:`top center`}),innerHTML:e.content},null,12,De)])])])])}}}),[[`__scopeId`,`data-v-e79a98a6`]]);const ke={class:`file-container excel-container`},Ae={class:`file-toolbar`},je={class:`flex justify-between items-center`},Me={class:`flex gap-2 items-center`},Ne={key:1,class:`text-sm text-gray-600`},Pe={class:`flex gap-2 items-center`},Fe={class:`excel-viewer`},Ie={key:0,class:`excel-info`},Le={class:`excel-table-container`},Re={key:0,class:`excel-table`},ze={class:`header-content`},Be={class:`column-letter`},Ve={class:`column-title`},He={class:`row-number`},Ue=[`rowspan`,`colspan`,`title`],We={key:1,class:`excel-empty`},Ge={key:0,class:`excel-pagination`};var Ke=e(l({__name:`index`,props:{sheets:{}},emits:[`reload`],setup(e){let l=e,u=g(``),p=g(!1),m=g(1),b=g(50),D=g([]),O=g([]),A=n(()=>Math.ceil(D.value.length/b.value)),j=n(()=>{let e=(m.value-1)*b.value;return D.value.slice(e,e+b.value)}),N=e=>{b.value=e,m.value=1},P=e=>{let t=l.sheets.find(t=>t.name===e);t&&(D.value=t.data,O.value=t.columns,m.value=1)};return C(u,e=>{P(e)}),C(()=>l.sheets,e=>{if(e.length>0){let[t]=e;u.value=t.name,D.value=t.data,O.value=t.columns,m.value=1}},{immediate:!0}),(e,n)=>{let l=v(`C_Icon`);return h(),a(`div`,ke,[i(` 工具栏 `),o(`div`,Ae,[o(`div`,je,[o(`div`,Me,[e.sheets.length>1?(h(),r(x(I),{key:0,value:u.value,"onUpdate:value":n[0]||=e=>u.value=e,type:`card`,size:`small`},{default:w(()=>[(h(!0),a(t,null,_(e.sheets,e=>(h(),r(x(F),{key:e.name,name:e.name,tab:e.name},null,8,[`name`,`tab`]))),128))]),_:1},8,[`value`])):(h(),a(`span`,Ne,` 工作表: `+y(u.value),1))]),o(`div`,Pe,[c(x(E),{size:`small`,onClick:n[1]||=e=>p.value=!p.value},{icon:w(()=>[c(l,{name:`ic:outline-format-paint`})]),default:w(()=>[s(` `+y(p.value?`紧凑视图`:`完整格式`),1)]),_:1})])])]),o(`div`,Fe,[i(` 信息面板 `),D.value.length>0?(h(),a(`div`,Ie,[c(x(R),{depth:`3`,class:`text-sm`},{default:w(()=>[s(` 当前工作表: `+y(u.value)+` | 总行数: `+y(D.value.length)+` | 总列数: `+y(O.value.length)+` | 当前页: `+y(m.value)+`/`+y(A.value),1)]),_:1})])):i(`v-if`,!0),i(` 表格 `),o(`div`,Le,[o(`div`,{class:d([`excel-table-wrapper`,{"simple-mode":!p.value}])},[D.value.length>0?(h(),a(`table`,Re,[o(`thead`,null,[o(`tr`,null,[n[4]||=o(`th`,{class:`row-number`},`行号`,-1),(h(!0),a(t,null,_(O.value,(e,t)=>(h(),a(`th`,{key:e.key,class:`excel-header`,style:f({minWidth:e.width+`px`})},[o(`div`,ze,[o(`span`,Be,y(x(ne)(t)),1),o(`span`,Ve,y(e.title),1)])],4))),128))])]),o(`tbody`,null,[(h(!0),a(t,null,_(j.value,(e,n)=>(h(),a(`tr`,{key:n,class:`excel-row`},[o(`td`,He,y((m.value-1)*b.value+n+1),1),(h(!0),a(t,null,_(O.value,t=>T((h(),a(`td`,{key:t.key,class:d([`excel-cell`,[x(Y)(e[t.key]?.value),e[t.key]?.merged?`merged-cell`:``,p.value?``:`compact-cell`]]),rowspan:e[t.key]?.rowspan||1,colspan:e[t.key]?.colspan||1,title:e[t.key]?.value},y(x(re)(e[t.key]?.value)),11,Ue)),[[S,!e[t.key]?.hidden]])),128))]))),128))])])):(h(),a(`div`,We,[c(x(k),{description:`该工作表没有数据或解析失败`},{extra:w(()=>[c(x(E),{size:`small`,onClick:n[2]||=t=>e.$emit(`reload`)},{default:w(()=>n[5]||=[s(` 重新解析 `,-1)]),_:1,__:[5]})]),_:1})]))],2),i(` 分页 `),A.value>1?(h(),a(`div`,Ge,[c(x(M),{page:m.value,"onUpdate:page":n[3]||=e=>m.value=e,"page-count":A.value,"page-size":b.value,"show-size-picker":``,"page-sizes":x(W),"onUpdate:pageSize":N},null,8,[`page`,`page-count`,`page-size`,`page-sizes`])])):i(`v-if`,!0)])])])}}}),[[`__scopeId`,`data-v-d1c1c8fe`]]);function Z(e,t){let{file:r,url:i,fileName:a}=e,o=g(!1),s=g(``),c=g(0),l=g(!1),u=g(``),d=g(0),f=g(``),p=g([]),h=g([]),_=n(()=>a.value&&a.value!==`未知文件`?a.value:r.value?.name?r.value.name:i.value?K(i.value):`未知文件`),v=n(()=>ee(_.value)),y=n(()=>te(v.value)),b=()=>{s.value=``,o.value=!1,u.value=``,d.value=0,f.value=``,p.value=[],h.value=[]},x=e=>{s.value=e,o.value=!1},S=async()=>{if(r.value)return c.value=r.value.size,r.value;if(i.value){let e=await fetch(i.value);if(!e.ok)throw Error(`HTTP ${e.status}: ${e.statusText}`);let t=await e.blob(),n=new File([t],_.value,{type:t.type});return c.value=n.size,n}throw Error(`未提供文件或URL`)},w=async(e,t)=>{switch(t){case`pdf`:{let t=await ie(e);u.value=t.url,d.value=t.totalPages;break}case`word`:{let t=await ae(e);f.value=t.content,p.value=t.headings;break}case`excel`:h.value=(await oe(e)).sheets;break;default:throw Error(`不支持的文件格式`)}},T=async()=>{if(!r.value&&!i.value){x(`未提供文件或URL`);return}b(),o.value=!0;try{await w(await S(),v.value),o.value=!1}catch(e){let t=e instanceof Error?e.message:`未知错误`;x(`${v.value.toUpperCase()}文件加载失败: ${t}`)}};return C(()=>r.value?.size,e=>{c.value=e||0},{immediate:!0}),m(()=>{u.value?.startsWith(`blob:`)&&URL.revokeObjectURL(u.value.split(`#`)[0])}),{loading:o,error:s,fileSize:c,showModal:l,pdfUrl:u,pdfTotalPages:d,wordContent:f,wordHeadings:p,excelSheets:h,displayFileName:_,fileType:v,fileConfig:y,loadFile:T,openPreview:async()=>{l.value=!0,await T(),t(`preview`,r.value||i.value)},downloadFile:()=>{if(r.value){let e=URL.createObjectURL(r.value);Object.assign(document.createElement(`a`),{href:e,download:_.value}).click(),URL.revokeObjectURL(e)}else i.value&&window.open(i.value,`_blank`);t(`download`,r.value||i.value)}}}function Q(e){let t=g(!1),n=()=>{t.value=!!document.fullscreenElement},r=(e,t=0)=>t>=e.length?(console.warn(`无法切换全屏状态`),Promise.resolve()):e[t]().catch(()=>r(e,t+1));return p(()=>{G.forEach(e=>document.addEventListener(e,n))}),m(()=>{G.forEach(e=>document.removeEventListener(e,n))}),{isFullscreen:t,toggleFullscreen:async()=>{let t=e.value;t&&await r(document.fullscreenElement?[()=>document.exitFullscreen(),()=>document.webkitExitFullscreen(),()=>document.mozCancelFullScreen(),()=>document.msExitFullscreen()]:[()=>t.requestFullscreen(),()=>t.webkitRequestFullscreen(),()=>t.mozRequestFullScreen(),()=>t.msRequestFullscreen()])},exitFullscreen:async()=>{if(document.fullscreenElement)try{await document.exitFullscreen()}catch{}t.value=!1}}}const qe={class:`c-file-preview-wrapper`},Je={key:0,class:`file-info-card`},Ye={class:`file-info`},Xe={class:`file-icon`},Ze={class:`file-details`},Qe={class:`file-name`},$e={class:`file-meta`},et={class:`file-size`},tt={class:`file-actions`},$={class:`modal-header`},nt={class:`modal-title`},rt={class:`modal-actions`},it={class:`modal-content`},at={class:`preview-header`},ot={class:`flex justify-between items-center`},st={class:`flex items-center gap-3`},ct={class:`text-sm text-gray-500`},lt={class:`flex gap-2`},ut={class:`preview-content`},dt={key:0,class:`status-container`};var ft=e(l({name:`C_FilePreview`,__name:`index`,props:{file:{},url:{},fileName:{default:`未知文件`},autoPreview:{type:Boolean,default:!1}},emits:[`preview`,`download`],setup(e,{emit:n}){let{file:l,url:d,fileName:f,autoPreview:p}=b(e),{loading:m,error:_,fileSize:S,showModal:T,pdfUrl:D,pdfTotalPages:k,wordContent:A,wordHeadings:M,excelSheets:F,displayFileName:I,fileType:R,fileConfig:z,loadFile:B,openPreview:V,downloadFile:H}=Z({file:l,url:d,fileName:f},n),U=g(),{isFullscreen:W,toggleFullscreen:G,exitFullscreen:K}=Q(U);return C(T,e=>{e||K()}),(e,n)=>{let l=v(`C_Icon`);return h(),a(`div`,qe,[i(` 文件信息卡片模式 `),x(p)?i(`v-if`,!0):(h(),a(`div`,Je,[o(`div`,Ye,[o(`div`,Xe,[c(l,{name:x(z).icon,size:40,color:x(z).color},null,8,[`name`,`color`])]),o(`div`,Ze,[o(`div`,Qe,[c(x(O),{style:{"max-width":`250px`}},{default:w(()=>[s(y(x(I)),1)]),_:1}),c(x(L),{type:x(z).tagType,size:`small`},{default:w(()=>[s(y(x(R).toUpperCase()),1)]),_:1},8,[`type`])]),o(`div`,$e,[o(`span`,et,y(x(q)(x(S))),1)])]),o(`div`,tt,[c(x(E),{type:`primary`,onClick:x(V)},{icon:w(()=>[c(l,{name:`ic:outline-visibility`})]),default:w(()=>[n[2]||=s(` 预览 `,-1)]),_:1,__:[2]},8,[`onClick`]),c(x(E),{type:`tertiary`,onClick:x(H)},{icon:w(()=>[c(l,{name:`ic:outline-download`})]),default:w(()=>[n[3]||=s(` 下载 `,-1)]),_:1,__:[3]},8,[`onClick`])])])])),i(` 模态框预览 `),c(x(j),{show:x(T),"onUpdate:show":n[1]||=e=>u(T)?T.value=e:null,"mask-closable":!1,closable:!1,"auto-focus":!1,"transform-origin":`center`,style:{width:`85vw`,"max-width":`1200px`,"min-width":`800px`,height:`75vh`,"max-height":`700px`,"min-height":`500px`}},{default:w(()=>[o(`div`,{ref_key:`modalContainer`,ref:U,class:`modal-container`},[i(` 自定义头部 `),o(`div`,$,[o(`div`,nt,[c(l,{name:x(z).icon,size:20,color:x(z).color},null,8,[`name`,`color`]),o(`span`,null,y(x(I)),1)]),o(`div`,rt,[c(x(E),{size:`small`,type:`tertiary`,onClick:x(H)},{icon:w(()=>[c(l,{name:`ic:outline-download`})]),default:w(()=>[n[4]||=s(` 下载 `,-1)]),_:1,__:[4]},8,[`onClick`]),c(x(E),{size:`small`,type:`tertiary`,onClick:n[0]||=e=>T.value=!1},{icon:w(()=>[c(l,{name:`ic:outline-close`})]),_:1})])]),i(` 预览内容 `),o(`div`,it,[i(` 文件信息头部 `),o(`div`,at,[o(`div`,ot,[o(`div`,st,[c(x(L),{type:x(z).tagType,size:`small`},{icon:w(()=>[c(l,{name:x(z).icon},null,8,[`name`])]),default:w(()=>[s(` `+y(x(R).toUpperCase()),1)]),_:1},8,[`type`]),c(x(O),{style:{"max-width":`300px`}},{default:w(()=>[s(y(x(I)),1)]),_:1}),o(`span`,ct,y(x(q)(x(S))),1)]),o(`div`,lt,[c(x(E),{size:`small`,type:`tertiary`,disabled:x(m),onClick:x(B)},{icon:w(()=>[c(l,{name:`ic:outline-refresh`})]),default:w(()=>[n[5]||=s(` 刷新 `,-1)]),_:1,__:[5]},8,[`disabled`,`onClick`]),c(x(E),{size:`small`,type:`primary`,onClick:x(G)},{icon:w(()=>[c(l,{name:x(W)?`ic:outline-fullscreen-exit`:`ic:outline-fullscreen`},null,8,[`name`])]),default:w(()=>[s(` `+y(x(W)?`退出全屏`:`全屏`),1)]),_:1},8,[`onClick`])])])]),i(` 预览内容区域 `),o(`div`,ut,[i(` 加载和错误状态 `),x(m)||x(_)?(h(),a(`div`,dt,[x(m)?(h(),r(x(P),{key:0,size:`large`},{description:w(()=>[s(` 正在加载`+y(x(R).toUpperCase())+`文件... `,1)]),_:1})):(h(),r(x(N),{key:1,status:`error`,title:`预览失败`,description:x(_)},{footer:w(()=>[c(x(E),{onClick:x(B)},{default:w(()=>n[6]||=[s(`重试`,-1)]),_:1,__:[6]},8,[`onClick`])]),_:1},8,[`description`]))])):(h(),a(t,{key:1},[i(` 文件预览 — 委托给子组件 `),x(R)===`pdf`?(h(),r(ge,{key:0,"pdf-url":x(D),"total-pages":x(k)},null,8,[`pdf-url`,`total-pages`])):x(R)===`word`?(h(),r(Oe,{key:1,content:x(A),headings:x(M)},null,8,[`content`,`headings`])):x(R)===`excel`?(h(),r(Ke,{key:2,sheets:x(F),onReload:x(B)},null,8,[`sheets`,`onReload`])):(h(),a(t,{key:3},[i(` 不支持的文件类型 `),c(x(N),{status:`warning`,title:`不支持的文件格式`,description:`暂不支持预览 ${x(R).toUpperCase()} 格式文件`},null,8,[`description`])],2112))],64))])])],512)]),_:1},8,[`show`])])}}}),[[`__scopeId`,`data-v-30d50866`]]);export{Q as n,Z as r,ft as t};
2
2
  //# sourceMappingURL=C_FilePreview2.js.map