@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_QRCode2.js","names":["showBorder","mode","size","showLabel","label"],"sources":["../src/components/C_QRCode/composables/useQRCode.ts","../src/components/C_QRCode/index.vue","../src/components/C_QRCode/index.vue","../src/components/C_QRCode/index.vue"],"sourcesContent":["import { ref, computed, watch } from \"vue\";\r\nimport QRCode from \"qrcode\";\r\nimport type { Ref } from \"vue\";\r\nimport type {\r\n ErrorCorrectionLevel,\r\n ExportType,\r\n LogoOptions,\r\n RenderMode,\r\n} from \"../types\";\r\n\r\ninterface UseQRCodeOptions {\r\n value: Ref<string>;\r\n size: Ref<number>;\r\n color: Ref<string>;\r\n bgColor: Ref<string>;\r\n errorCorrectionLevel: Ref<ErrorCorrectionLevel>;\r\n margin: Ref<number>;\r\n mode: Ref<RenderMode>;\r\n logo: Ref<LogoOptions | undefined>;\r\n}\r\n\r\nfunction drawLogo(\r\n canvas: HTMLCanvasElement,\r\n logo: LogoOptions,\r\n qrSize: number,\r\n): Promise<void> {\r\n return new Promise((resolve, reject) => {\r\n const ctx = canvas.getContext(\"2d\");\r\n if (!ctx) return reject(new Error(\"Canvas context 不可用\"));\r\n\r\n const img = new Image();\r\n img.crossOrigin = \"anonymous\";\r\n img.onload = () => {\r\n const ratio = logo.size ?? 0.2;\r\n const logoSize = Math.floor(qrSize * ratio);\r\n const padding = logo.padding ?? 4;\r\n const borderRadius = logo.borderRadius ?? 4;\r\n\r\n const x = (canvas.width - logoSize) / 2;\r\n const y = (canvas.height - logoSize) / 2;\r\n\r\n ctx.save();\r\n const bgX = x - padding;\r\n const bgY = y - padding;\r\n const bgSize = logoSize + padding * 2;\r\n const r = borderRadius + padding;\r\n\r\n ctx.beginPath();\r\n ctx.moveTo(bgX + r, bgY);\r\n ctx.arcTo(bgX + bgSize, bgY, bgX + bgSize, bgY + bgSize, r);\r\n ctx.arcTo(bgX + bgSize, bgY + bgSize, bgX, bgY + bgSize, r);\r\n ctx.arcTo(bgX, bgY + bgSize, bgX, bgY, r);\r\n ctx.arcTo(bgX, bgY, bgX + bgSize, bgY, r);\r\n ctx.closePath();\r\n ctx.fillStyle = logo.bgColor ?? \"#ffffff\";\r\n ctx.fill();\r\n\r\n ctx.beginPath();\r\n ctx.moveTo(x + borderRadius, y);\r\n ctx.arcTo(x + logoSize, y, x + logoSize, y + logoSize, borderRadius);\r\n ctx.arcTo(x + logoSize, y + logoSize, x, y + logoSize, borderRadius);\r\n ctx.arcTo(x, y + logoSize, x, y, borderRadius);\r\n ctx.arcTo(x, y, x + logoSize, y, borderRadius);\r\n ctx.closePath();\r\n ctx.clip();\r\n ctx.drawImage(img, x, y, logoSize, logoSize);\r\n ctx.restore();\r\n\r\n resolve();\r\n };\r\n img.onerror = () => reject(new Error(`Logo 加载失败: ${logo.src}`));\r\n img.src = logo.src;\r\n });\r\n}\r\n\r\nexport function useQRCode(\r\n canvasRef: Ref<HTMLCanvasElement | null>,\r\n options: UseQRCodeOptions,\r\n) {\r\n const svgHtml = ref(\"\");\r\n const error = ref<Error | null>(null);\r\n const loading = ref(false);\r\n\r\n const effectiveLevel = computed<ErrorCorrectionLevel>(() => {\r\n if (options.logo.value) {\r\n const level = options.errorCorrectionLevel.value;\r\n if (level === \"L\" || level === \"M\") return \"Q\";\r\n return level;\r\n }\r\n return options.errorCorrectionLevel.value;\r\n });\r\n\r\n const qrOptions = computed(() => ({\r\n width: options.size.value,\r\n margin: options.margin.value,\r\n errorCorrectionLevel: effectiveLevel.value,\r\n color: {\r\n dark: options.color.value,\r\n light: options.bgColor.value,\r\n },\r\n }));\r\n\r\n async function renderCanvas() {\r\n const canvas = canvasRef.value;\r\n if (!canvas || !options.value.value) return;\r\n await QRCode.toCanvas(canvas, options.value.value, qrOptions.value);\r\n if (options.logo.value) {\r\n await drawLogo(canvas, options.logo.value, options.size.value);\r\n }\r\n }\r\n\r\n async function renderSvg() {\r\n if (!options.value.value) {\r\n svgHtml.value = \"\";\r\n return;\r\n }\r\n const svgString = await QRCode.toString(options.value.value, {\r\n ...qrOptions.value,\r\n type: \"svg\",\r\n });\r\n svgHtml.value = svgString;\r\n }\r\n\r\n async function render() {\r\n if (!options.value.value) return;\r\n loading.value = true;\r\n error.value = null;\r\n try {\r\n if (options.mode.value === \"canvas\") {\r\n await renderCanvas();\r\n } else {\r\n await renderSvg();\r\n }\r\n } catch (e) {\r\n error.value = e instanceof Error ? e : new Error(String(e));\r\n console.error(\"二维码渲染失败:\", e);\r\n } finally {\r\n loading.value = false;\r\n }\r\n }\r\n\r\n async function toDataURL(\r\n type: ExportType = \"png\",\r\n quality = 0.92,\r\n ): Promise<string> {\r\n if (type === \"svg\") {\r\n const svgStr = await QRCode.toString(options.value.value, {\r\n ...qrOptions.value,\r\n type: \"svg\",\r\n });\r\n return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svgStr)}`;\r\n }\r\n const tempCanvas = document.createElement(\"canvas\");\r\n await QRCode.toCanvas(tempCanvas, options.value.value, qrOptions.value);\r\n if (options.logo.value) {\r\n await drawLogo(tempCanvas, options.logo.value, options.size.value);\r\n }\r\n const mimeType = type === \"jpeg\" ? \"image/jpeg\" : \"image/png\";\r\n return tempCanvas.toDataURL(mimeType, quality);\r\n }\r\n\r\n async function download(filename = \"qrcode\", type: ExportType = \"png\") {\r\n const dataUrl = await toDataURL(type);\r\n const link = document.createElement(\"a\");\r\n link.download = `${filename}.${type}`;\r\n link.href = dataUrl;\r\n link.click();\r\n }\r\n\r\n watch(\r\n [\r\n options.value,\r\n options.size,\r\n options.color,\r\n options.bgColor,\r\n options.errorCorrectionLevel,\r\n options.margin,\r\n options.mode,\r\n options.logo,\r\n ],\r\n () => render(),\r\n { deep: true },\r\n );\r\n\r\n return { svgHtml, error, loading, render, toDataURL, download };\r\n}\r\n","/* unplugin-vue-components disabled */<!--\r\n * @Author: ChenYu ycyplus@gmail.com\r\n * @Date: 2025-06-16\r\n * @Description: 二维码组件\r\n * @Migration: naive-ui-components 组件库迁移版本\r\n * Copyright (c) 2025 by CHENY, All Rights Reserved.\r\n-->\r\n<template>\r\n <div class=\"c-qrcode\">\r\n <div class=\"qrcode-wrapper\" :class=\"{ 'with-border': showBorder }\">\r\n <canvas v-show=\"mode === 'canvas'\" ref=\"canvasRef\" />\r\n <div\r\n v-if=\"mode === 'svg'\"\r\n class=\"qrcode-svg\"\r\n :style=\"{ width: `${size}px`, height: `${size}px` }\"\r\n v-html=\"svgHtml\"\r\n />\r\n </div>\r\n <div v-if=\"showLabel && label\" class=\"qrcode-label\">\r\n {{ label }}\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref, toRef, watch, onMounted } from \"vue\";\r\nimport { useQRCode } from \"./composables/useQRCode\";\r\nimport type {\r\n ErrorCorrectionLevel,\r\n ExportType,\r\n LogoOptions,\r\n QRCodeExpose,\r\n RenderMode,\r\n} from \"./types\";\r\n\r\ndefineOptions({ name: \"C_QRCode\" });\r\n\r\ninterface Props {\r\n value: string;\r\n size?: number;\r\n color?: string;\r\n bgColor?: string;\r\n errorCorrectionLevel?: ErrorCorrectionLevel;\r\n margin?: number;\r\n mode?: RenderMode;\r\n logo?: LogoOptions;\r\n showBorder?: boolean;\r\n label?: string;\r\n showLabel?: boolean;\r\n}\r\n\r\nconst props = withDefaults(defineProps<Props>(), {\r\n size: 200,\r\n color: \"#000000\",\r\n bgColor: \"#FFFFFF\",\r\n errorCorrectionLevel: \"M\",\r\n margin: 2,\r\n mode: \"canvas\",\r\n logo: undefined,\r\n showBorder: true,\r\n label: \"\",\r\n showLabel: false,\r\n});\r\n\r\nconst emit = defineEmits<{\r\n error: [error: Error];\r\n}>();\r\n\r\nconst canvasRef = ref<HTMLCanvasElement | null>(null);\r\n\r\nconst { svgHtml, error, render, toDataURL, download } = useQRCode(canvasRef, {\r\n value: toRef(props, \"value\"),\r\n size: toRef(props, \"size\"),\r\n color: toRef(props, \"color\"),\r\n bgColor: toRef(props, \"bgColor\"),\r\n errorCorrectionLevel: toRef(props, \"errorCorrectionLevel\"),\r\n margin: toRef(props, \"margin\"),\r\n mode: toRef(props, \"mode\"),\r\n logo: toRef(props, \"logo\"),\r\n});\r\n\r\nwatch(error, (e) => {\r\n if (e) emit(\"error\", e);\r\n});\r\n\r\nonMounted(() => render());\r\n\r\ndefineExpose<QRCodeExpose>({\r\n toDataURL: (type?: ExportType, quality?: number) => toDataURL(type, quality),\r\n download: (filename?: string, type?: ExportType) => download(filename, type),\r\n refresh: () => render(),\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-06-16\r\n * @Description: 二维码组件\r\n * @Migration: naive-ui-components 组件库迁移版本\r\n * Copyright (c) 2025 by CHENY, All Rights Reserved.\r\n-->\r\n<template>\r\n <div class=\"c-qrcode\">\r\n <div class=\"qrcode-wrapper\" :class=\"{ 'with-border': showBorder }\">\r\n <canvas v-show=\"mode === 'canvas'\" ref=\"canvasRef\" />\r\n <div\r\n v-if=\"mode === 'svg'\"\r\n class=\"qrcode-svg\"\r\n :style=\"{ width: `${size}px`, height: `${size}px` }\"\r\n v-html=\"svgHtml\"\r\n />\r\n </div>\r\n <div v-if=\"showLabel && label\" class=\"qrcode-label\">\r\n {{ label }}\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref, toRef, watch, onMounted } from \"vue\";\r\nimport { useQRCode } from \"./composables/useQRCode\";\r\nimport type {\r\n ErrorCorrectionLevel,\r\n ExportType,\r\n LogoOptions,\r\n QRCodeExpose,\r\n RenderMode,\r\n} from \"./types\";\r\n\r\ndefineOptions({ name: \"C_QRCode\" });\r\n\r\ninterface Props {\r\n value: string;\r\n size?: number;\r\n color?: string;\r\n bgColor?: string;\r\n errorCorrectionLevel?: ErrorCorrectionLevel;\r\n margin?: number;\r\n mode?: RenderMode;\r\n logo?: LogoOptions;\r\n showBorder?: boolean;\r\n label?: string;\r\n showLabel?: boolean;\r\n}\r\n\r\nconst props = withDefaults(defineProps<Props>(), {\r\n size: 200,\r\n color: \"#000000\",\r\n bgColor: \"#FFFFFF\",\r\n errorCorrectionLevel: \"M\",\r\n margin: 2,\r\n mode: \"canvas\",\r\n logo: undefined,\r\n showBorder: true,\r\n label: \"\",\r\n showLabel: false,\r\n});\r\n\r\nconst emit = defineEmits<{\r\n error: [error: Error];\r\n}>();\r\n\r\nconst canvasRef = ref<HTMLCanvasElement | null>(null);\r\n\r\nconst { svgHtml, error, render, toDataURL, download } = useQRCode(canvasRef, {\r\n value: toRef(props, \"value\"),\r\n size: toRef(props, \"size\"),\r\n color: toRef(props, \"color\"),\r\n bgColor: toRef(props, \"bgColor\"),\r\n errorCorrectionLevel: toRef(props, \"errorCorrectionLevel\"),\r\n margin: toRef(props, \"margin\"),\r\n mode: toRef(props, \"mode\"),\r\n logo: toRef(props, \"logo\"),\r\n});\r\n\r\nwatch(error, (e) => {\r\n if (e) emit(\"error\", e);\r\n});\r\n\r\nonMounted(() => render());\r\n\r\ndefineExpose<QRCodeExpose>({\r\n toDataURL: (type?: ExportType, quality?: number) => toDataURL(type, quality),\r\n download: (filename?: string, type?: ExportType) => download(filename, type),\r\n refresh: () => render(),\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-06-16\r\n * @Description: 二维码组件\r\n * @Migration: naive-ui-components 组件库迁移版本\r\n * Copyright (c) 2025 by CHENY, All Rights Reserved.\r\n-->\r\n<template>\r\n <div class=\"c-qrcode\">\r\n <div class=\"qrcode-wrapper\" :class=\"{ 'with-border': showBorder }\">\r\n <canvas v-show=\"mode === 'canvas'\" ref=\"canvasRef\" />\r\n <div\r\n v-if=\"mode === 'svg'\"\r\n class=\"qrcode-svg\"\r\n :style=\"{ width: `${size}px`, height: `${size}px` }\"\r\n v-html=\"svgHtml\"\r\n />\r\n </div>\r\n <div v-if=\"showLabel && label\" class=\"qrcode-label\">\r\n {{ label }}\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref, toRef, watch, onMounted } from \"vue\";\r\nimport { useQRCode } from \"./composables/useQRCode\";\r\nimport type {\r\n ErrorCorrectionLevel,\r\n ExportType,\r\n LogoOptions,\r\n QRCodeExpose,\r\n RenderMode,\r\n} from \"./types\";\r\n\r\ndefineOptions({ name: \"C_QRCode\" });\r\n\r\ninterface Props {\r\n value: string;\r\n size?: number;\r\n color?: string;\r\n bgColor?: string;\r\n errorCorrectionLevel?: ErrorCorrectionLevel;\r\n margin?: number;\r\n mode?: RenderMode;\r\n logo?: LogoOptions;\r\n showBorder?: boolean;\r\n label?: string;\r\n showLabel?: boolean;\r\n}\r\n\r\nconst props = withDefaults(defineProps<Props>(), {\r\n size: 200,\r\n color: \"#000000\",\r\n bgColor: \"#FFFFFF\",\r\n errorCorrectionLevel: \"M\",\r\n margin: 2,\r\n mode: \"canvas\",\r\n logo: undefined,\r\n showBorder: true,\r\n label: \"\",\r\n showLabel: false,\r\n});\r\n\r\nconst emit = defineEmits<{\r\n error: [error: Error];\r\n}>();\r\n\r\nconst canvasRef = ref<HTMLCanvasElement | null>(null);\r\n\r\nconst { svgHtml, error, render, toDataURL, download } = useQRCode(canvasRef, {\r\n value: toRef(props, \"value\"),\r\n size: toRef(props, \"size\"),\r\n color: toRef(props, \"color\"),\r\n bgColor: toRef(props, \"bgColor\"),\r\n errorCorrectionLevel: toRef(props, \"errorCorrectionLevel\"),\r\n margin: toRef(props, \"margin\"),\r\n mode: toRef(props, \"mode\"),\r\n logo: toRef(props, \"logo\"),\r\n});\r\n\r\nwatch(error, (e) => {\r\n if (e) emit(\"error\", e);\r\n});\r\n\r\nonMounted(() => render());\r\n\r\ndefineExpose<QRCodeExpose>({\r\n toDataURL: (type?: ExportType, quality?: number) => toDataURL(type, quality),\r\n download: (filename?: string, type?: ExportType) => download(filename, type),\r\n refresh: () => render(),\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_QRCode2.js","names":[],"sources":["../src/components/C_QRCode/composables/useQRCode.ts","../src/components/C_QRCode/index.vue"],"sourcesContent":["import { ref, computed, watch } from \"vue\";\r\nimport QRCode from \"qrcode\";\r\nimport type { Ref } from \"vue\";\r\nimport type {\r\n ErrorCorrectionLevel,\r\n ExportType,\r\n LogoOptions,\r\n RenderMode,\r\n} from \"../types\";\r\n\r\ninterface UseQRCodeOptions {\r\n value: Ref<string>;\r\n size: Ref<number>;\r\n color: Ref<string>;\r\n bgColor: Ref<string>;\r\n errorCorrectionLevel: Ref<ErrorCorrectionLevel>;\r\n margin: Ref<number>;\r\n mode: Ref<RenderMode>;\r\n logo: Ref<LogoOptions | undefined>;\r\n}\r\n\r\nfunction drawLogo(\r\n canvas: HTMLCanvasElement,\r\n logo: LogoOptions,\r\n qrSize: number,\r\n): Promise<void> {\r\n return new Promise((resolve, reject) => {\r\n const ctx = canvas.getContext(\"2d\");\r\n if (!ctx) return reject(new Error(\"Canvas context 不可用\"));\r\n\r\n const img = new Image();\r\n img.crossOrigin = \"anonymous\";\r\n img.onload = () => {\r\n const ratio = logo.size ?? 0.2;\r\n const logoSize = Math.floor(qrSize * ratio);\r\n const padding = logo.padding ?? 4;\r\n const borderRadius = logo.borderRadius ?? 4;\r\n\r\n const x = (canvas.width - logoSize) / 2;\r\n const y = (canvas.height - logoSize) / 2;\r\n\r\n ctx.save();\r\n const bgX = x - padding;\r\n const bgY = y - padding;\r\n const bgSize = logoSize + padding * 2;\r\n const r = borderRadius + padding;\r\n\r\n ctx.beginPath();\r\n ctx.moveTo(bgX + r, bgY);\r\n ctx.arcTo(bgX + bgSize, bgY, bgX + bgSize, bgY + bgSize, r);\r\n ctx.arcTo(bgX + bgSize, bgY + bgSize, bgX, bgY + bgSize, r);\r\n ctx.arcTo(bgX, bgY + bgSize, bgX, bgY, r);\r\n ctx.arcTo(bgX, bgY, bgX + bgSize, bgY, r);\r\n ctx.closePath();\r\n ctx.fillStyle = logo.bgColor ?? \"#ffffff\";\r\n ctx.fill();\r\n\r\n ctx.beginPath();\r\n ctx.moveTo(x + borderRadius, y);\r\n ctx.arcTo(x + logoSize, y, x + logoSize, y + logoSize, borderRadius);\r\n ctx.arcTo(x + logoSize, y + logoSize, x, y + logoSize, borderRadius);\r\n ctx.arcTo(x, y + logoSize, x, y, borderRadius);\r\n ctx.arcTo(x, y, x + logoSize, y, borderRadius);\r\n ctx.closePath();\r\n ctx.clip();\r\n ctx.drawImage(img, x, y, logoSize, logoSize);\r\n ctx.restore();\r\n\r\n resolve();\r\n };\r\n img.onerror = () => reject(new Error(`Logo 加载失败: ${logo.src}`));\r\n img.src = logo.src;\r\n });\r\n}\r\n\r\nexport function useQRCode(\r\n canvasRef: Ref<HTMLCanvasElement | null>,\r\n options: UseQRCodeOptions,\r\n) {\r\n const svgHtml = ref(\"\");\r\n const error = ref<Error | null>(null);\r\n const loading = ref(false);\r\n\r\n const effectiveLevel = computed<ErrorCorrectionLevel>(() => {\r\n if (options.logo.value) {\r\n const level = options.errorCorrectionLevel.value;\r\n if (level === \"L\" || level === \"M\") return \"Q\";\r\n return level;\r\n }\r\n return options.errorCorrectionLevel.value;\r\n });\r\n\r\n const qrOptions = computed(() => ({\r\n width: options.size.value,\r\n margin: options.margin.value,\r\n errorCorrectionLevel: effectiveLevel.value,\r\n color: {\r\n dark: options.color.value,\r\n light: options.bgColor.value,\r\n },\r\n }));\r\n\r\n async function renderCanvas() {\r\n const canvas = canvasRef.value;\r\n if (!canvas || !options.value.value) return;\r\n await QRCode.toCanvas(canvas, options.value.value, qrOptions.value);\r\n if (options.logo.value) {\r\n await drawLogo(canvas, options.logo.value, options.size.value);\r\n }\r\n }\r\n\r\n async function renderSvg() {\r\n if (!options.value.value) {\r\n svgHtml.value = \"\";\r\n return;\r\n }\r\n const svgString = await QRCode.toString(options.value.value, {\r\n ...qrOptions.value,\r\n type: \"svg\",\r\n });\r\n svgHtml.value = svgString;\r\n }\r\n\r\n async function render() {\r\n if (!options.value.value) return;\r\n loading.value = true;\r\n error.value = null;\r\n try {\r\n if (options.mode.value === \"canvas\") {\r\n await renderCanvas();\r\n } else {\r\n await renderSvg();\r\n }\r\n } catch (e) {\r\n error.value = e instanceof Error ? e : new Error(String(e));\r\n console.error(\"二维码渲染失败:\", e);\r\n } finally {\r\n loading.value = false;\r\n }\r\n }\r\n\r\n async function toDataURL(\r\n type: ExportType = \"png\",\r\n quality = 0.92,\r\n ): Promise<string> {\r\n if (type === \"svg\") {\r\n const svgStr = await QRCode.toString(options.value.value, {\r\n ...qrOptions.value,\r\n type: \"svg\",\r\n });\r\n return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svgStr)}`;\r\n }\r\n const tempCanvas = document.createElement(\"canvas\");\r\n await QRCode.toCanvas(tempCanvas, options.value.value, qrOptions.value);\r\n if (options.logo.value) {\r\n await drawLogo(tempCanvas, options.logo.value, options.size.value);\r\n }\r\n const mimeType = type === \"jpeg\" ? \"image/jpeg\" : \"image/png\";\r\n return tempCanvas.toDataURL(mimeType, quality);\r\n }\r\n\r\n async function download(filename = \"qrcode\", type: ExportType = \"png\") {\r\n const dataUrl = await toDataURL(type);\r\n const link = document.createElement(\"a\");\r\n link.download = `${filename}.${type}`;\r\n link.href = dataUrl;\r\n link.click();\r\n }\r\n\r\n watch(\r\n [\r\n options.value,\r\n options.size,\r\n options.color,\r\n options.bgColor,\r\n options.errorCorrectionLevel,\r\n options.margin,\r\n options.mode,\r\n options.logo,\r\n ],\r\n () => render(),\r\n { deep: true },\r\n );\r\n\r\n return { svgHtml, error, loading, render, toDataURL, download };\r\n}\r\n","<!--\n * @Author: ChenYu ycyplus@gmail.com\n * @Date: 2025-06-16\n * @Description: 二维码组件\n * @Migration: naive-ui-components 组件库迁移版本\n * Copyright (c) 2025 by CHENY, All Rights Reserved.\n-->\n<template>\n <div class=\"c-qrcode\">\n <div class=\"qrcode-wrapper\" :class=\"{ 'with-border': showBorder }\">\n <canvas v-show=\"mode === 'canvas'\" ref=\"canvasRef\" />\n <div\n v-if=\"mode === 'svg'\"\n class=\"qrcode-svg\"\n :style=\"{ width: `${size}px`, height: `${size}px` }\"\n v-html=\"svgHtml\"\n />\n </div>\n <div v-if=\"showLabel && label\" class=\"qrcode-label\">\n {{ label }}\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, toRef, watch, onMounted } from \"vue\";\nimport { useQRCode } from \"./composables/useQRCode\";\nimport type {\n ErrorCorrectionLevel,\n ExportType,\n LogoOptions,\n QRCodeExpose,\n RenderMode,\n} from \"./types\";\n\ndefineOptions({ name: \"C_QRCode\" });\n\ninterface Props {\n value: string;\n size?: number;\n color?: string;\n bgColor?: string;\n errorCorrectionLevel?: ErrorCorrectionLevel;\n margin?: number;\n mode?: RenderMode;\n logo?: LogoOptions;\n showBorder?: boolean;\n label?: string;\n showLabel?: boolean;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n size: 200,\n color: \"#000000\",\n bgColor: \"#FFFFFF\",\n errorCorrectionLevel: \"M\",\n margin: 2,\n mode: \"canvas\",\n logo: undefined,\n showBorder: true,\n label: \"\",\n showLabel: false,\n});\n\nconst emit = defineEmits<{\n error: [error: Error];\n}>();\n\nconst canvasRef = ref<HTMLCanvasElement | null>(null);\n\nconst { svgHtml, error, render, toDataURL, download } = useQRCode(canvasRef, {\n value: toRef(props, \"value\"),\n size: toRef(props, \"size\"),\n color: toRef(props, \"color\"),\n bgColor: toRef(props, \"bgColor\"),\n errorCorrectionLevel: toRef(props, \"errorCorrectionLevel\"),\n margin: toRef(props, \"margin\"),\n mode: toRef(props, \"mode\"),\n logo: toRef(props, \"logo\"),\n});\n\nwatch(error, (e) => {\n if (e) emit(\"error\", e);\n});\n\nonMounted(() => render());\n\ndefineExpose<QRCodeExpose>({\n toDataURL: (type?: ExportType, quality?: number) => toDataURL(type, quality),\n download: (filename?: string, type?: ExportType) => download(filename, type),\n refresh: () => render(),\n});\n</script>\n\n<style lang=\"scss\" scoped>\n@use \"./index.scss\";\n</style>\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"C_Signature-BJMvVPWT.css","names":[],"sources":["../src/components/C_Signature/index.vue?vue&type=style&index=0&scoped=1c733bfe&lang.scss"],"sourcesContent":["/* unplugin-vue-components disabled *//* 电子签名组件样式 */\n.c-signature[data-v-1c733bfe] {\n display: flex;\n flex-direction: column;\n gap: 12px;\n width: 100%;\n}\n.c-signature .signature-toolbar[data-v-1c733bfe] {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 12px;\n background: var(--c-bg-card, #fff);\n border: 1px solid var(--c-border, #e1e4e8);\n border-radius: var(--c-radius, 6px);\n flex-wrap: wrap;\n}\n.c-signature .signature-toolbar .toolbar-section[data-v-1c733bfe] {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n.c-signature .signature-toolbar .toolbar-section.divider[data-v-1c733bfe] {\n width: 1px;\n height: 24px;\n background: var(--c-border, #e1e4e8);\n margin: 0 4px;\n}\n.c-signature .signature-toolbar .toolbar-section .section-label[data-v-1c733bfe] {\n font-size: 13px;\n color: var(--c-text-3, #999);\n font-weight: 500;\n white-space: nowrap;\n flex-shrink: 0;\n}\n.c-signature .signature-toolbar .toolbar-section .n-color-picker[data-v-1c733bfe] {\n width: 90px !important;\n flex-shrink: 0;\n}\n.c-signature .signature-canvas-wrapper[data-v-1c733bfe] {\n position: relative;\n border: 1px solid var(--c-border, #e1e4e8);\n border-radius: var(--c-radius, 6px);\n overflow: hidden;\n background: var(--c-bg, #fff);\n transition: border-color 0.3s;\n}\n.c-signature .signature-canvas-wrapper[data-v-1c733bfe]:hover {\n border-color: var(--c-primary, #409eff);\n}\n.c-signature .signature-canvas-wrapper.disabled[data-v-1c733bfe] {\n opacity: 0.6;\n cursor: not-allowed;\n border-color: var(--c-border, #e1e4e8);\n}\n.c-signature .signature-canvas-wrapper.readonly[data-v-1c733bfe] {\n cursor: default;\n}\n.c-signature .signature-canvas-wrapper .signature-canvas[data-v-1c733bfe] {\n display: block;\n width: 100%;\n height: 100%;\n cursor: crosshair;\n touch-action: none;\n}\n.c-signature .signature-canvas-wrapper .signature-canvas.disabled[data-v-1c733bfe], .c-signature .signature-canvas-wrapper .signature-canvas.readonly[data-v-1c733bfe] {\n cursor: not-allowed;\n}\n.c-signature .signature-canvas-wrapper .canvas-placeholder[data-v-1c733bfe] {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n color: var(--c-text-4, #ccc);\n font-size: 14px;\n pointer-events: none;\n user-select: none;\n}\n.c-signature .signature-actions[data-v-1c733bfe] {\n display: flex;\n justify-content: flex-end;\n gap: 8px;\n}"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA"}
1
+ {"version":3,"file":"C_Signature-BDx4ctsE.css","names":[],"sources":["../src/components/C_Signature/index.vue?vue&type=style&index=0&scoped=fbc647a9&lang.scss"],"sourcesContent":["/* unplugin-vue-components disabled *//* 电子签名组件样式 */\n.c-signature[data-v-fbc647a9] {\n display: flex;\n flex-direction: column;\n gap: 12px;\n width: 100%;\n}\n.c-signature .signature-toolbar[data-v-fbc647a9] {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 12px;\n background: var(--c-bg-card, #fff);\n border: 1px solid var(--c-border, #e1e4e8);\n border-radius: var(--c-radius, 6px);\n flex-wrap: wrap;\n}\n.c-signature .signature-toolbar .toolbar-section[data-v-fbc647a9] {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n.c-signature .signature-toolbar .toolbar-section.divider[data-v-fbc647a9] {\n width: 1px;\n height: 24px;\n background: var(--c-border, #e1e4e8);\n margin: 0 4px;\n}\n.c-signature .signature-toolbar .toolbar-section .section-label[data-v-fbc647a9] {\n font-size: 13px;\n color: var(--c-text-3, #999);\n font-weight: 500;\n white-space: nowrap;\n flex-shrink: 0;\n}\n.c-signature .signature-toolbar .toolbar-section .n-color-picker[data-v-fbc647a9] {\n width: 90px !important;\n flex-shrink: 0;\n}\n.c-signature .signature-canvas-wrapper[data-v-fbc647a9] {\n position: relative;\n border: 1px solid var(--c-border, #e1e4e8);\n border-radius: var(--c-radius, 6px);\n overflow: hidden;\n background: var(--c-bg, #fff);\n transition: border-color 0.3s;\n}\n.c-signature .signature-canvas-wrapper[data-v-fbc647a9]:hover {\n border-color: var(--c-primary, #409eff);\n}\n.c-signature .signature-canvas-wrapper.disabled[data-v-fbc647a9] {\n opacity: 0.6;\n cursor: not-allowed;\n border-color: var(--c-border, #e1e4e8);\n}\n.c-signature .signature-canvas-wrapper.readonly[data-v-fbc647a9] {\n cursor: default;\n}\n.c-signature .signature-canvas-wrapper .signature-canvas[data-v-fbc647a9] {\n display: block;\n width: 100%;\n height: 100%;\n cursor: crosshair;\n touch-action: none;\n}\n.c-signature .signature-canvas-wrapper .signature-canvas.disabled[data-v-fbc647a9], .c-signature .signature-canvas-wrapper .signature-canvas.readonly[data-v-fbc647a9] {\n cursor: not-allowed;\n}\n.c-signature .signature-canvas-wrapper .canvas-placeholder[data-v-fbc647a9] {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n color: var(--c-text-4, #ccc);\n font-size: 14px;\n pointer-events: none;\n user-select: none;\n}\n.c-signature .signature-actions[data-v-fbc647a9] {\n display: flex;\n justify-content: flex-end;\n gap: 8px;\n}"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA"}
@@ -1 +1 @@
1
- {"version":3,"file":"C_Signature-BJUHx2BF.css","names":[],"sources":["../src/components/C_Signature/index.vue?vue&type=style&index=0&scoped=1c733bfe&lang.scss"],"sourcesContent":["/* unplugin-vue-components disabled *//* 电子签名组件样式 */\n.c-signature[data-v-1c733bfe] {\n display: flex;\n flex-direction: column;\n gap: 12px;\n width: 100%;\n}\n.c-signature .signature-toolbar[data-v-1c733bfe] {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 12px;\n background: var(--c-bg-card, #fff);\n border: 1px solid var(--c-border, #e1e4e8);\n border-radius: var(--c-radius, 6px);\n flex-wrap: wrap;\n}\n.c-signature .signature-toolbar .toolbar-section[data-v-1c733bfe] {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n.c-signature .signature-toolbar .toolbar-section.divider[data-v-1c733bfe] {\n width: 1px;\n height: 24px;\n background: var(--c-border, #e1e4e8);\n margin: 0 4px;\n}\n.c-signature .signature-toolbar .toolbar-section .section-label[data-v-1c733bfe] {\n font-size: 13px;\n color: var(--c-text-3, #999);\n font-weight: 500;\n white-space: nowrap;\n flex-shrink: 0;\n}\n.c-signature .signature-toolbar .toolbar-section .n-color-picker[data-v-1c733bfe] {\n width: 90px !important;\n flex-shrink: 0;\n}\n.c-signature .signature-canvas-wrapper[data-v-1c733bfe] {\n position: relative;\n border: 1px solid var(--c-border, #e1e4e8);\n border-radius: var(--c-radius, 6px);\n overflow: hidden;\n background: var(--c-bg, #fff);\n transition: border-color 0.3s;\n}\n.c-signature .signature-canvas-wrapper[data-v-1c733bfe]:hover {\n border-color: var(--c-primary, #409eff);\n}\n.c-signature .signature-canvas-wrapper.disabled[data-v-1c733bfe] {\n opacity: 0.6;\n cursor: not-allowed;\n border-color: var(--c-border, #e1e4e8);\n}\n.c-signature .signature-canvas-wrapper.readonly[data-v-1c733bfe] {\n cursor: default;\n}\n.c-signature .signature-canvas-wrapper .signature-canvas[data-v-1c733bfe] {\n display: block;\n width: 100%;\n height: 100%;\n cursor: crosshair;\n touch-action: none;\n}\n.c-signature .signature-canvas-wrapper .signature-canvas.disabled[data-v-1c733bfe], .c-signature .signature-canvas-wrapper .signature-canvas.readonly[data-v-1c733bfe] {\n cursor: not-allowed;\n}\n.c-signature .signature-canvas-wrapper .canvas-placeholder[data-v-1c733bfe] {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n color: var(--c-text-4, #ccc);\n font-size: 14px;\n pointer-events: none;\n user-select: none;\n}\n.c-signature .signature-actions[data-v-1c733bfe] {\n display: flex;\n justify-content: flex-end;\n gap: 8px;\n}"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA"}
1
+ {"version":3,"file":"C_Signature-Bz_uNbwv.css","names":[],"sources":["../src/components/C_Signature/index.vue?vue&type=style&index=0&scoped=fbc647a9&lang.scss"],"sourcesContent":["/* unplugin-vue-components disabled *//* 电子签名组件样式 */\n.c-signature[data-v-fbc647a9] {\n display: flex;\n flex-direction: column;\n gap: 12px;\n width: 100%;\n}\n.c-signature .signature-toolbar[data-v-fbc647a9] {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 12px;\n background: var(--c-bg-card, #fff);\n border: 1px solid var(--c-border, #e1e4e8);\n border-radius: var(--c-radius, 6px);\n flex-wrap: wrap;\n}\n.c-signature .signature-toolbar .toolbar-section[data-v-fbc647a9] {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n.c-signature .signature-toolbar .toolbar-section.divider[data-v-fbc647a9] {\n width: 1px;\n height: 24px;\n background: var(--c-border, #e1e4e8);\n margin: 0 4px;\n}\n.c-signature .signature-toolbar .toolbar-section .section-label[data-v-fbc647a9] {\n font-size: 13px;\n color: var(--c-text-3, #999);\n font-weight: 500;\n white-space: nowrap;\n flex-shrink: 0;\n}\n.c-signature .signature-toolbar .toolbar-section .n-color-picker[data-v-fbc647a9] {\n width: 90px !important;\n flex-shrink: 0;\n}\n.c-signature .signature-canvas-wrapper[data-v-fbc647a9] {\n position: relative;\n border: 1px solid var(--c-border, #e1e4e8);\n border-radius: var(--c-radius, 6px);\n overflow: hidden;\n background: var(--c-bg, #fff);\n transition: border-color 0.3s;\n}\n.c-signature .signature-canvas-wrapper[data-v-fbc647a9]:hover {\n border-color: var(--c-primary, #409eff);\n}\n.c-signature .signature-canvas-wrapper.disabled[data-v-fbc647a9] {\n opacity: 0.6;\n cursor: not-allowed;\n border-color: var(--c-border, #e1e4e8);\n}\n.c-signature .signature-canvas-wrapper.readonly[data-v-fbc647a9] {\n cursor: default;\n}\n.c-signature .signature-canvas-wrapper .signature-canvas[data-v-fbc647a9] {\n display: block;\n width: 100%;\n height: 100%;\n cursor: crosshair;\n touch-action: none;\n}\n.c-signature .signature-canvas-wrapper .signature-canvas.disabled[data-v-fbc647a9], .c-signature .signature-canvas-wrapper .signature-canvas.readonly[data-v-fbc647a9] {\n cursor: not-allowed;\n}\n.c-signature .signature-canvas-wrapper .canvas-placeholder[data-v-fbc647a9] {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n color: var(--c-text-4, #ccc);\n font-size: 14px;\n pointer-events: none;\n user-select: none;\n}\n.c-signature .signature-actions[data-v-fbc647a9] {\n display: flex;\n justify-content: flex-end;\n gap: 8px;\n}"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA"}
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`}),require(`./C_Icon.js`);const e=require(`./C_Signature.js`);exports.C_Signature=e.t,exports.useSignatureCanvas=e.i,exports.useSignatureExport=e.n,exports.useSignatureHistory=e.r;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./C_Signature.js`);exports.C_Signature=e.t,exports.useSignatureCanvas=e.i,exports.useSignatureExport=e.n,exports.useSignatureHistory=e.r;
@@ -1,11 +1,11 @@
1
1
  /* unplugin-vue-components disabled *//* 电子签名组件样式 */
2
- .c-signature[data-v-1c733bfe] {
2
+ .c-signature[data-v-fbc647a9] {
3
3
  display: flex;
4
4
  flex-direction: column;
5
5
  gap: 12px;
6
6
  width: 100%;
7
7
  }
8
- .c-signature .signature-toolbar[data-v-1c733bfe] {
8
+ .c-signature .signature-toolbar[data-v-fbc647a9] {
9
9
  display: flex;
10
10
  align-items: center;
11
11
  gap: 12px;
@@ -15,29 +15,29 @@
15
15
  border-radius: var(--c-radius, 6px);
16
16
  flex-wrap: wrap;
17
17
  }
18
- .c-signature .signature-toolbar .toolbar-section[data-v-1c733bfe] {
18
+ .c-signature .signature-toolbar .toolbar-section[data-v-fbc647a9] {
19
19
  display: flex;
20
20
  align-items: center;
21
21
  gap: 8px;
22
22
  }
23
- .c-signature .signature-toolbar .toolbar-section.divider[data-v-1c733bfe] {
23
+ .c-signature .signature-toolbar .toolbar-section.divider[data-v-fbc647a9] {
24
24
  width: 1px;
25
25
  height: 24px;
26
26
  background: var(--c-border, #e1e4e8);
27
27
  margin: 0 4px;
28
28
  }
29
- .c-signature .signature-toolbar .toolbar-section .section-label[data-v-1c733bfe] {
29
+ .c-signature .signature-toolbar .toolbar-section .section-label[data-v-fbc647a9] {
30
30
  font-size: 13px;
31
31
  color: var(--c-text-3, #999);
32
32
  font-weight: 500;
33
33
  white-space: nowrap;
34
34
  flex-shrink: 0;
35
35
  }
36
- .c-signature .signature-toolbar .toolbar-section .n-color-picker[data-v-1c733bfe] {
36
+ .c-signature .signature-toolbar .toolbar-section .n-color-picker[data-v-fbc647a9] {
37
37
  width: 90px !important;
38
38
  flex-shrink: 0;
39
39
  }
40
- .c-signature .signature-canvas-wrapper[data-v-1c733bfe] {
40
+ .c-signature .signature-canvas-wrapper[data-v-fbc647a9] {
41
41
  position: relative;
42
42
  border: 1px solid var(--c-border, #e1e4e8);
43
43
  border-radius: var(--c-radius, 6px);
@@ -45,28 +45,28 @@
45
45
  background: var(--c-bg, #fff);
46
46
  transition: border-color 0.3s;
47
47
  }
48
- .c-signature .signature-canvas-wrapper[data-v-1c733bfe]:hover {
48
+ .c-signature .signature-canvas-wrapper[data-v-fbc647a9]:hover {
49
49
  border-color: var(--c-primary, #409eff);
50
50
  }
51
- .c-signature .signature-canvas-wrapper.disabled[data-v-1c733bfe] {
51
+ .c-signature .signature-canvas-wrapper.disabled[data-v-fbc647a9] {
52
52
  opacity: 0.6;
53
53
  cursor: not-allowed;
54
54
  border-color: var(--c-border, #e1e4e8);
55
55
  }
56
- .c-signature .signature-canvas-wrapper.readonly[data-v-1c733bfe] {
56
+ .c-signature .signature-canvas-wrapper.readonly[data-v-fbc647a9] {
57
57
  cursor: default;
58
58
  }
59
- .c-signature .signature-canvas-wrapper .signature-canvas[data-v-1c733bfe] {
59
+ .c-signature .signature-canvas-wrapper .signature-canvas[data-v-fbc647a9] {
60
60
  display: block;
61
61
  width: 100%;
62
62
  height: 100%;
63
63
  cursor: crosshair;
64
64
  touch-action: none;
65
65
  }
66
- .c-signature .signature-canvas-wrapper .signature-canvas.disabled[data-v-1c733bfe], .c-signature .signature-canvas-wrapper .signature-canvas.readonly[data-v-1c733bfe] {
66
+ .c-signature .signature-canvas-wrapper .signature-canvas.disabled[data-v-fbc647a9], .c-signature .signature-canvas-wrapper .signature-canvas.readonly[data-v-fbc647a9] {
67
67
  cursor: not-allowed;
68
68
  }
69
- .c-signature .signature-canvas-wrapper .canvas-placeholder[data-v-1c733bfe] {
69
+ .c-signature .signature-canvas-wrapper .canvas-placeholder[data-v-fbc647a9] {
70
70
  position: absolute;
71
71
  top: 50%;
72
72
  left: 50%;
@@ -76,10 +76,10 @@
76
76
  pointer-events: none;
77
77
  user-select: none;
78
78
  }
79
- .c-signature .signature-actions[data-v-1c733bfe] {
79
+ .c-signature .signature-actions[data-v-fbc647a9] {
80
80
  display: flex;
81
81
  justify-content: flex-end;
82
82
  gap: 8px;
83
83
  }
84
84
 
85
- /*# sourceMappingURL=C_Signature-BJMvVPWT.css.map*/
85
+ /*# sourceMappingURL=C_Signature-BDx4ctsE.css.map*/
@@ -1 +1 @@
1
- import"./C_Icon2.js";import{i as e,n as t,r as n,t as r}from"./C_Signature2.js";export{r as C_Signature,e as useSignatureCanvas,t as useSignatureExport,n as useSignatureHistory};
1
+ import{i as e,n as t,r as n,t as r}from"./C_Signature2.js";export{r as C_Signature,e as useSignatureCanvas,t as useSignatureExport,n as useSignatureHistory};
@@ -1 +1 @@
1
- {"version":3,"file":"C_Signature.js","names":["showToolbar","disabled","readonly","width","height","backgroundColor"],"sources":["../src/components/C_Signature/composables/useSignatureCanvas.ts","../src/components/C_Signature/composables/useSignatureHistory.ts","../src/components/C_Signature/composables/useSignatureExport.ts","../src/components/C_Signature/data.ts","../src/components/C_Signature/index.vue","../src/components/C_Signature/index.vue","../src/components/C_Signature/index.vue"],"sourcesContent":["import type { Ref } from \"vue\";\r\nimport { ref, readonly } from \"vue\";\r\nimport type {\r\n PenConfig,\r\n PenMode,\r\n SignaturePoint,\r\n SignatureStroke,\r\n} from \"../types\";\r\n\r\ninterface UseSignatureCanvasOptions {\r\n canvasRef: Ref<HTMLCanvasElement | null>;\r\n penConfig: Ref<PenConfig>;\r\n mode: Ref<PenMode>;\r\n disabled: Ref<boolean>;\r\n onStrokeComplete: (stroke: SignatureStroke) => void;\r\n onDrawStart: () => void;\r\n onDrawing: (point: SignaturePoint) => void;\r\n}\r\n\r\nexport function useSignatureCanvas(options: UseSignatureCanvasOptions) {\r\n const {\r\n canvasRef,\r\n penConfig,\r\n mode,\r\n disabled,\r\n onStrokeComplete,\r\n onDrawStart,\r\n onDrawing,\r\n } = options;\r\n\r\n const isDrawing = ref(false);\r\n const currentStroke = ref<SignaturePoint[]>([]);\r\n let ctx: CanvasRenderingContext2D | null = null;\r\n\r\n const initCanvas = () => {\r\n const canvas = canvasRef.value;\r\n if (!canvas) return;\r\n ctx = canvas.getContext(\"2d\", { willReadFrequently: true });\r\n if (!ctx) return;\r\n const dpr = window.devicePixelRatio || 1;\r\n const rect = canvas.getBoundingClientRect();\r\n canvas.width = rect.width * dpr;\r\n canvas.height = rect.height * dpr;\r\n canvas.style.width = `${rect.width}px`;\r\n canvas.style.height = `${rect.height}px`;\r\n ctx.scale(dpr, dpr);\r\n ctx.lineCap = \"round\";\r\n ctx.lineJoin = \"round\";\r\n };\r\n\r\n const getPointFromEvent = (e: MouseEvent | TouchEvent): SignaturePoint => {\r\n const canvas = canvasRef.value;\r\n if (!canvas) return { x: 0, y: 0 };\r\n const rect = canvas.getBoundingClientRect();\r\n let clientX: number;\r\n let clientY: number;\r\n if (\"touches\" in e && e.touches.length > 0) {\r\n ({ clientX, clientY } = e.touches[0]);\r\n } else if (\"clientX\" in e) {\r\n ({ clientX, clientY } = e);\r\n } else {\r\n return { x: 0, y: 0 };\r\n }\r\n return {\r\n x: clientX - rect.left,\r\n y: clientY - rect.top,\r\n timestamp: Date.now(),\r\n };\r\n };\r\n\r\n const drawStroke = (\r\n from: SignaturePoint,\r\n to: SignaturePoint,\r\n config: PenConfig,\r\n eraserMode = false,\r\n ) => {\r\n if (!ctx) return;\r\n ctx.save();\r\n if (eraserMode) {\r\n ctx.globalCompositeOperation = \"destination-out\";\r\n ctx.lineWidth = 20;\r\n } else {\r\n ctx.globalCompositeOperation = \"source-over\";\r\n ctx.strokeStyle = config.color;\r\n ctx.lineWidth = config.width;\r\n ctx.globalAlpha = config.opacity;\r\n }\r\n ctx.beginPath();\r\n ctx.moveTo(from.x, from.y);\r\n ctx.lineTo(to.x, to.y);\r\n ctx.stroke();\r\n ctx.restore();\r\n };\r\n\r\n const startDrawing = (e: MouseEvent | TouchEvent) => {\r\n if (disabled.value) return;\r\n e.preventDefault();\r\n isDrawing.value = true;\r\n currentStroke.value = [];\r\n const point = getPointFromEvent(e);\r\n currentStroke.value.push(point);\r\n onDrawStart();\r\n };\r\n\r\n const draw = (e: MouseEvent | TouchEvent) => {\r\n if (!isDrawing.value || disabled.value) return;\r\n e.preventDefault();\r\n const point = getPointFromEvent(e);\r\n const lastPoint = currentStroke.value[currentStroke.value.length - 1];\r\n if (lastPoint) {\r\n drawStroke(lastPoint, point, penConfig.value, mode.value === \"eraser\");\r\n }\r\n currentStroke.value.push(point);\r\n onDrawing(point);\r\n };\r\n\r\n const endDrawing = (e: MouseEvent | TouchEvent) => {\r\n if (!isDrawing.value || disabled.value) return;\r\n e.preventDefault();\r\n isDrawing.value = false;\r\n if (currentStroke.value.length > 0) {\r\n const stroke: SignatureStroke = {\r\n points: [...currentStroke.value],\r\n color: penConfig.value.color,\r\n width: penConfig.value.width,\r\n opacity: penConfig.value.opacity,\r\n mode: mode.value,\r\n };\r\n onStrokeComplete(stroke);\r\n currentStroke.value = [];\r\n }\r\n };\r\n\r\n const redrawStrokes = (strokes: SignatureStroke[]) => {\r\n if (!ctx || !canvasRef.value) return;\r\n const canvas = canvasRef.value;\r\n ctx.clearRect(0, 0, canvas.width, canvas.height);\r\n strokes.forEach((stroke) => {\r\n for (let i = 1; i < stroke.points.length; i++) {\r\n drawStroke(\r\n stroke.points[i - 1],\r\n stroke.points[i],\r\n { color: stroke.color, width: stroke.width, opacity: stroke.opacity },\r\n stroke.mode === \"eraser\",\r\n );\r\n }\r\n });\r\n };\r\n\r\n const clearCanvas = () => {\r\n if (!ctx || !canvasRef.value) return;\r\n ctx.clearRect(0, 0, canvasRef.value.width, canvasRef.value.height);\r\n };\r\n\r\n const bindEvents = () => {\r\n const canvas = canvasRef.value;\r\n if (!canvas) return;\r\n canvas.addEventListener(\"mousedown\", startDrawing);\r\n canvas.addEventListener(\"mousemove\", draw);\r\n canvas.addEventListener(\"mouseup\", endDrawing);\r\n canvas.addEventListener(\"mouseleave\", endDrawing);\r\n canvas.addEventListener(\"touchstart\", startDrawing, { passive: false });\r\n canvas.addEventListener(\"touchmove\", draw, { passive: false });\r\n canvas.addEventListener(\"touchend\", endDrawing);\r\n canvas.addEventListener(\"touchcancel\", endDrawing);\r\n };\r\n\r\n const unbindEvents = () => {\r\n const canvas = canvasRef.value;\r\n if (!canvas) return;\r\n canvas.removeEventListener(\"mousedown\", startDrawing);\r\n canvas.removeEventListener(\"mousemove\", draw);\r\n canvas.removeEventListener(\"mouseup\", endDrawing);\r\n canvas.removeEventListener(\"mouseleave\", endDrawing);\r\n canvas.removeEventListener(\"touchstart\", startDrawing);\r\n canvas.removeEventListener(\"touchmove\", draw);\r\n canvas.removeEventListener(\"touchend\", endDrawing);\r\n canvas.removeEventListener(\"touchcancel\", endDrawing);\r\n };\r\n\r\n return {\r\n isDrawing: readonly(isDrawing),\r\n initCanvas,\r\n bindEvents,\r\n unbindEvents,\r\n redrawStrokes,\r\n clearCanvas,\r\n };\r\n}\r\n","import { ref, computed, readonly } from \"vue\";\r\nimport type { SignatureStroke } from \"../types\";\r\n\r\ninterface UseSignatureHistoryOptions {\r\n maxHistory?: number;\r\n onChange?: (strokes: SignatureStroke[]) => void;\r\n}\r\n\r\nexport function useSignatureHistory(options: UseSignatureHistoryOptions = {}) {\r\n const { maxHistory = 50, onChange } = options;\r\n\r\n const strokes = ref<SignatureStroke[]>([]);\r\n const historyStack = ref<SignatureStroke[][]>([]);\r\n const historyIndex = ref(-1);\r\n\r\n const canUndo = computed(() => historyIndex.value > 0);\r\n const canRedo = computed(\r\n () => historyIndex.value < historyStack.value.length - 1,\r\n );\r\n\r\n const addStroke = (stroke: SignatureStroke) => {\r\n strokes.value.push(stroke);\r\n saveToHistory();\r\n };\r\n\r\n const saveToHistory = () => {\r\n historyStack.value = historyStack.value.slice(0, historyIndex.value + 1);\r\n historyStack.value.push([...strokes.value]);\r\n historyIndex.value++;\r\n if (historyStack.value.length > maxHistory) {\r\n historyStack.value.shift();\r\n historyIndex.value--;\r\n }\r\n onChange?.(strokes.value);\r\n };\r\n\r\n const undo = (): boolean => {\r\n if (!canUndo.value) return false;\r\n historyIndex.value--;\r\n strokes.value = [...historyStack.value[historyIndex.value]];\r\n onChange?.(strokes.value);\r\n return true;\r\n };\r\n\r\n const redo = (): boolean => {\r\n if (!canRedo.value) return false;\r\n historyIndex.value++;\r\n strokes.value = [...historyStack.value[historyIndex.value]];\r\n onChange?.(strokes.value);\r\n return true;\r\n };\r\n\r\n const clear = () => {\r\n strokes.value = [];\r\n historyStack.value = [[]];\r\n historyIndex.value = 0;\r\n onChange?.(strokes.value);\r\n };\r\n\r\n const loadData = (data: SignatureStroke[]) => {\r\n strokes.value = [...data];\r\n historyStack.value = [[...data]];\r\n historyIndex.value = 0;\r\n onChange?.(strokes.value);\r\n };\r\n\r\n const isEmpty = computed(() => strokes.value.length === 0);\r\n\r\n // 初始化历史栈\r\n historyStack.value = [[]];\r\n historyIndex.value = 0;\r\n\r\n return {\r\n strokes: readonly(strokes),\r\n canUndo: readonly(canUndo),\r\n canRedo: readonly(canRedo),\r\n isEmpty: readonly(isEmpty),\r\n addStroke,\r\n undo,\r\n redo,\r\n clear,\r\n loadData,\r\n };\r\n}\r\n","import type { Ref } from 'vue'\r\nimport type { ExportOptions, WatermarkConfig } from '../types'\r\n\r\ninterface UseSignatureExportOptions {\r\n canvasRef: Ref<HTMLCanvasElement | null>\r\n watermark?: Ref<Partial<WatermarkConfig>>\r\n}\r\n\r\n/**\r\n *\r\n */\r\nexport function useSignatureExport(options: UseSignatureExportOptions) {\r\n const { canvasRef, watermark } = options\r\n\r\n const getWatermarkPosition = (\r\n canvas: HTMLCanvasElement,\r\n textWidth: number,\r\n fontSize: number,\r\n position: string\r\n ): { x: number; y: number } => {\r\n const padding = 10\r\n const positions = {\r\n 'top-left': { x: padding, y: fontSize + padding },\r\n 'top-right': {\r\n x: canvas.width - textWidth - padding,\r\n y: fontSize + padding,\r\n },\r\n 'bottom-left': { x: padding, y: canvas.height - padding },\r\n 'bottom-right': {\r\n x: canvas.width - textWidth - padding,\r\n y: canvas.height - padding,\r\n },\r\n }\r\n return (\r\n positions[position as keyof typeof positions] || positions['bottom-right']\r\n )\r\n }\r\n\r\n const drawWatermark = (canvas: HTMLCanvasElement, text: string): void => {\r\n const ctx = canvas.getContext('2d')\r\n if (!ctx || !watermark?.value?.show) return\r\n const config = {\r\n fontSize: watermark.value.fontSize || 12,\r\n color: watermark.value.color || '#999999',\r\n position: watermark.value.position || 'bottom-right',\r\n }\r\n ctx.save()\r\n ctx.font = `${config.fontSize}px Arial`\r\n ctx.fillStyle = config.color\r\n ctx.textBaseline = 'bottom'\r\n const textWidth = ctx.measureText(text).width\r\n const { x, y } = getWatermarkPosition(\r\n canvas,\r\n textWidth,\r\n config.fontSize,\r\n config.position\r\n )\r\n ctx.fillText(text, x, y)\r\n ctx.restore()\r\n }\r\n\r\n const createTempCanvas = (\r\n sourceCanvas: HTMLCanvasElement,\r\n includeBackground: boolean,\r\n backgroundColor: string\r\n ) => {\r\n const tempCanvas = document.createElement('canvas')\r\n tempCanvas.width = sourceCanvas.width\r\n tempCanvas.height = sourceCanvas.height\r\n const tempCtx = tempCanvas.getContext('2d')\r\n if (!tempCtx) throw new Error('无法创建临时 Canvas')\r\n if (includeBackground) {\r\n tempCtx.fillStyle = backgroundColor\r\n tempCtx.fillRect(0, 0, tempCanvas.width, tempCanvas.height)\r\n }\r\n tempCtx.drawImage(sourceCanvas, 0, 0)\r\n return { canvas: tempCanvas, ctx: tempCtx }\r\n }\r\n\r\n const prepareExportCanvas = (\r\n canvas: HTMLCanvasElement,\r\n options: ExportOptions\r\n ): HTMLCanvasElement => {\r\n const {\r\n includeBackground = false,\r\n backgroundColor = '#FFFFFF',\r\n includeWatermark = false,\r\n } = options\r\n const { canvas: tempCanvas } = createTempCanvas(\r\n canvas,\r\n includeBackground,\r\n backgroundColor\r\n )\r\n // includeWatermark 为 true 时才叠加水印,无视 watermark.show 的状态\r\n // 这样「不含水印导出」即使组件配置了水印也不会叠加\r\n if (includeWatermark && watermark?.value?.text) {\r\n drawWatermark(tempCanvas, watermark.value.text)\r\n }\r\n return tempCanvas\r\n }\r\n\r\n const exportToBlob = (\r\n canvas: HTMLCanvasElement,\r\n quality: number\r\n ): Promise<Blob> => {\r\n return new Promise<Blob>((resolve, reject) => {\r\n canvas.toBlob(\r\n blob => (blob ? resolve(blob) : reject(new Error('导出失败'))),\r\n 'image/png',\r\n quality\r\n )\r\n })\r\n }\r\n\r\n const isCanvasEmpty = (canvas: HTMLCanvasElement): boolean => {\r\n const ctx = canvas.getContext('2d')\r\n if (!ctx) return true\r\n const { data } = ctx.getImageData(0, 0, canvas.width, canvas.height)\r\n return !data.some(v => v !== 0)\r\n }\r\n\r\n const exportSignature = async (\r\n options: ExportOptions = {}\r\n ): Promise<string | Blob> => {\r\n const canvas = canvasRef.value\r\n if (!canvas) throw new Error('Canvas 未初始化')\r\n if (isCanvasEmpty(canvas)) throw new Error('签名为空,请先签名后再导出')\r\n const { format = 'png', quality = 0.92 } = options\r\n if (format === 'svg') {\r\n return 'data:image/svg+xml;charset=utf-8,<svg xmlns=\"http://www.w3.org/2000/svg\"><text>SVG export placeholder</text></svg>'\r\n }\r\n const tempCanvas = prepareExportCanvas(canvas, options)\r\n if (format === 'blob') return exportToBlob(tempCanvas, quality)\r\n const mimeType = format === 'jpeg' ? 'image/jpeg' : 'image/png'\r\n return tempCanvas.toDataURL(mimeType, quality)\r\n }\r\n\r\n const download = async (\r\n filename = 'signature',\r\n options: ExportOptions = {}\r\n ): Promise<void> => {\r\n const format = options.format || 'png'\r\n const result = await exportSignature({ ...options, format })\r\n if (result instanceof Blob) {\r\n const url = URL.createObjectURL(result)\r\n const link = document.createElement('a')\r\n link.href = url\r\n link.download = `${filename}.${format}`\r\n link.click()\r\n URL.revokeObjectURL(url)\r\n } else if (typeof result === 'string') {\r\n const link = document.createElement('a')\r\n link.href = result\r\n link.download = `${filename}.${format}`\r\n link.click()\r\n }\r\n }\r\n\r\n const loadImage = async (imageUrl: string): Promise<void> => {\r\n const canvas = canvasRef.value\r\n if (!canvas) throw new Error('Canvas 未初始化')\r\n const ctx = canvas.getContext('2d')\r\n if (!ctx) throw new Error('无法获取 Canvas 上下文')\r\n return new Promise((resolve, reject) => {\r\n const img = new Image()\r\n img.crossOrigin = 'anonymous'\r\n img.onload = () => {\r\n ctx.clearRect(0, 0, canvas.width, canvas.height)\r\n ctx.drawImage(img, 0, 0, canvas.width, canvas.height)\r\n resolve()\r\n }\r\n img.onerror = () => reject(new Error(`图片加载失败: ${imageUrl}`))\r\n img.src = imageUrl\r\n })\r\n }\r\n\r\n return { exportSignature, download, loadImage }\r\n}\r\n","import type { EraserConfig, PenConfig, WatermarkConfig } from \"./types\";\r\n\r\nexport const DEFAULT_PEN_CONFIG: PenConfig = {\r\n color: \"#000000\",\r\n width: 2,\r\n opacity: 1,\r\n};\r\n\r\nexport const DEFAULT_ERASER_CONFIG: EraserConfig = { size: 20 };\r\n\r\nexport const DEFAULT_WATERMARK_CONFIG: WatermarkConfig = {\r\n show: false,\r\n text: \"\",\r\n fontSize: 12,\r\n color: \"#999999\",\r\n position: \"bottom-right\",\r\n};\r\n\r\nexport const PRESET_COLORS = [\r\n \"#000000\",\r\n \"#FF0000\",\r\n \"#0000FF\",\r\n \"#00AA00\",\r\n \"#FF6600\",\r\n \"#9900FF\",\r\n];\r\n\r\nexport const PRESET_WIDTHS = [1, 2, 3, 5, 8];\r\n\r\nexport const EXPORT_FORMAT_OPTIONS = [\r\n { label: \"PNG\", value: \"png\" },\r\n { label: \"JPEG\", value: \"jpeg\" },\r\n { label: \"SVG\", value: \"svg\" },\r\n { label: \"Blob\", value: \"blob\" },\r\n] as const;\r\n\r\nexport const WATERMARK_POSITION_OPTIONS = [\r\n { label: \"左上\", value: \"top-left\" },\r\n { label: \"右上\", value: \"top-right\" },\r\n { label: \"左下\", value: \"bottom-left\" },\r\n { label: \"右下\", value: \"bottom-right\" },\r\n] as const;\r\n","/* unplugin-vue-components disabled */<!--\r\n * @Author: ChenYu ycyplus@gmail.com\r\n * @Date: 2026-02-25\r\n * @Description: 电子签名组件\r\n * @Migration: naive-ui-components 组件库迁移版本\r\n * Copyright (c) 2026 by CHENY, All Rights Reserved.\r\n-->\r\n<template>\r\n <div class=\"c-signature\">\r\n <div v-if=\"showToolbar\" class=\"signature-toolbar\">\r\n <div class=\"toolbar-section\">\r\n <NButtonGroup>\r\n <NButton\r\n :type=\"currentMode === 'pen' ? 'primary' : 'default'\"\r\n size=\"small\"\r\n @click=\"currentMode = 'pen'\"\r\n >\r\n <template #icon>\r\n <C_Icon name=\"mdi:draw\" :size=\"16\" color=\"currentColor\" />\r\n </template>\r\n 画笔\r\n </NButton>\r\n <NButton\r\n :type=\"currentMode === 'eraser' ? 'primary' : 'default'\"\r\n size=\"small\"\r\n @click=\"currentMode = 'eraser'\"\r\n >\r\n <template #icon>\r\n <C_Icon name=\"mdi:eraser\" :size=\"16\" color=\"currentColor\" />\r\n </template>\r\n 橡皮擦\r\n </NButton>\r\n </NButtonGroup>\r\n </div>\r\n\r\n <div class=\"toolbar-section divider\" />\r\n\r\n <div v-if=\"currentMode === 'pen'\" class=\"toolbar-section\">\r\n <span class=\"section-label\">颜色</span>\r\n <NColorPicker\r\n v-model:value=\"currentPenConfig.color\"\r\n :show-alpha=\"false\"\r\n size=\"small\"\r\n :swatches=\"PRESET_COLORS\"\r\n />\r\n </div>\r\n\r\n <div v-if=\"currentMode === 'pen'\" class=\"toolbar-section\">\r\n <span class=\"section-label\">粗细</span>\r\n <NInputNumber\r\n v-model:value=\"currentPenConfig.width\"\r\n :min=\"1\"\r\n :max=\"20\"\r\n size=\"small\"\r\n style=\"width: 80px\"\r\n />\r\n </div>\r\n\r\n <div class=\"toolbar-section divider\" />\r\n\r\n <div class=\"toolbar-section\">\r\n <NButton size=\"small\" :disabled=\"!canUndo\" @click=\"handleUndo\">\r\n <template #icon>\r\n <C_Icon name=\"mdi:undo\" :size=\"16\" color=\"currentColor\" />\r\n </template>\r\n 撤销\r\n </NButton>\r\n <NButton size=\"small\" :disabled=\"!canRedo\" @click=\"handleRedo\">\r\n <template #icon>\r\n <C_Icon name=\"mdi:redo\" :size=\"16\" color=\"currentColor\" />\r\n </template>\r\n 重做\r\n </NButton>\r\n </div>\r\n\r\n <div class=\"toolbar-section divider\" />\r\n\r\n <div class=\"toolbar-section\">\r\n <NButton\r\n size=\"small\"\r\n type=\"error\"\r\n :disabled=\"isEmpty\"\r\n @click=\"handleClear\"\r\n >\r\n <template #icon>\r\n <C_Icon name=\"mdi:delete-outline\" :size=\"16\" color=\"currentColor\" />\r\n </template>\r\n 清空\r\n </NButton>\r\n </div>\r\n </div>\r\n\r\n <div\r\n class=\"signature-canvas-wrapper\"\r\n :class=\"{ disabled, readonly }\"\r\n :style=\"{\r\n width: typeof width === 'number' ? `${width}px` : width,\r\n height: typeof height === 'number' ? `${height}px` : height,\r\n backgroundColor: backgroundColor || 'transparent',\r\n }\"\r\n >\r\n <canvas\r\n ref=\"canvasRef\"\r\n class=\"signature-canvas\"\r\n :class=\"{ disabled, readonly }\"\r\n />\r\n <div v-if=\"isEmpty && !disabled && !readonly\" class=\"canvas-placeholder\">\r\n 请在此处签名\r\n </div>\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref, reactive, toRef, onMounted, onUnmounted } from \"vue\";\r\nimport { NButton, NButtonGroup, NColorPicker, NInputNumber } from \"naive-ui\";\r\nimport C_Icon from \"../C_Icon/index.vue\";\r\nimport { useSignatureCanvas } from \"./composables/useSignatureCanvas\";\r\nimport { useSignatureHistory } from \"./composables/useSignatureHistory\";\r\nimport { useSignatureExport } from \"./composables/useSignatureExport\";\r\nimport {\r\n DEFAULT_PEN_CONFIG,\r\n DEFAULT_WATERMARK_CONFIG,\r\n PRESET_COLORS,\r\n} from \"./data\";\r\nimport type {\r\n ExportOptions,\r\n PenConfig,\r\n PenMode,\r\n SignatureExpose,\r\n SignaturePoint,\r\n SignatureProps,\r\n SignatureStroke,\r\n WatermarkConfig,\r\n} from \"./types\";\r\n\r\ndefineOptions({ name: \"C_Signature\" });\r\n\r\nconst props = withDefaults(defineProps<SignatureProps>(), {\r\n width: \"100%\",\r\n height: 300,\r\n disabled: false,\r\n readonly: false,\r\n showToolbar: true,\r\n maxHistory: 50,\r\n});\r\n\r\nconst emit = defineEmits<{\r\n \"start-draw\": [];\r\n drawing: [point: SignaturePoint];\r\n \"end-draw\": [stroke: SignatureStroke];\r\n clear: [];\r\n undo: [];\r\n redo: [];\r\n change: [data: SignatureStroke[]];\r\n}>();\r\n\r\nconst canvasRef = ref<HTMLCanvasElement | null>(null);\r\nconst currentMode = ref<PenMode>(\"pen\");\r\nconst currentPenConfig = reactive<PenConfig>({\r\n ...DEFAULT_PEN_CONFIG,\r\n ...props.penConfig,\r\n});\r\nconst currentWatermark = reactive<WatermarkConfig>({\r\n ...DEFAULT_WATERMARK_CONFIG,\r\n ...props.watermark,\r\n});\r\n\r\nconst {\r\n strokes,\r\n canUndo,\r\n canRedo,\r\n isEmpty,\r\n addStroke,\r\n undo,\r\n redo,\r\n clear,\r\n loadData,\r\n} = useSignatureHistory({\r\n maxHistory: props.maxHistory,\r\n onChange: (data) => {\r\n canvasInstance.redrawStrokes(data as SignatureStroke[]);\r\n emit(\"change\", data as SignatureStroke[]);\r\n },\r\n});\r\n\r\nconst canvasInstance = useSignatureCanvas({\r\n canvasRef,\r\n penConfig: toRef(currentPenConfig),\r\n mode: currentMode,\r\n disabled: toRef(props, \"disabled\"),\r\n onStrokeComplete: (stroke: SignatureStroke) => {\r\n addStroke(stroke);\r\n emit(\"end-draw\", stroke);\r\n },\r\n onDrawStart: () => emit(\"start-draw\"),\r\n onDrawing: (point: SignaturePoint) => emit(\"drawing\", point),\r\n});\r\n\r\nconst exportInstance = useSignatureExport({\r\n canvasRef,\r\n watermark: toRef(currentWatermark),\r\n});\r\n\r\nconst handleUndo = (): boolean => {\r\n const result = undo();\r\n if (result) emit(\"undo\");\r\n return result;\r\n};\r\n\r\nconst handleRedo = (): boolean => {\r\n const result = redo();\r\n if (result) emit(\"redo\");\r\n return result;\r\n};\r\n\r\nconst handleClear = () => {\r\n clear();\r\n canvasInstance.clearCanvas();\r\n emit(\"clear\");\r\n};\r\n\r\nconst exportSignature = async (\r\n options?: ExportOptions,\r\n): Promise<string | Blob> => {\r\n return exportInstance.exportSignature(options);\r\n};\r\n\r\nconst download = async (\r\n filename?: string,\r\n options?: ExportOptions,\r\n): Promise<void> => {\r\n return exportInstance.download(filename, options);\r\n};\r\n\r\nconst loadImage = async (imageUrl: string): Promise<void> => {\r\n await exportInstance.loadImage(imageUrl);\r\n clear();\r\n};\r\n\r\nconst getSignatureData = (): SignatureStroke[] =>\r\n strokes.value as SignatureStroke[];\r\nconst loadSignatureData = (data: SignatureStroke[]): void => loadData(data);\r\nconst isSignatureEmpty = (): boolean => isEmpty.value;\r\n\r\nonMounted(() => {\r\n canvasInstance.initCanvas();\r\n canvasInstance.bindEvents();\r\n if (props.backgroundImage) loadImage(props.backgroundImage);\r\n});\r\n\r\nonUnmounted(() => canvasInstance.unbindEvents());\r\n\r\ndefineExpose<SignatureExpose>({\r\n clear: handleClear,\r\n undo: handleUndo,\r\n redo: handleRedo,\r\n export: exportSignature,\r\n download,\r\n loadImage,\r\n getSignatureData,\r\n loadSignatureData,\r\n isEmpty: isSignatureEmpty,\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: 2026-02-25\r\n * @Description: 电子签名组件\r\n * @Migration: naive-ui-components 组件库迁移版本\r\n * Copyright (c) 2026 by CHENY, All Rights Reserved.\r\n-->\r\n<template>\r\n <div class=\"c-signature\">\r\n <div v-if=\"showToolbar\" class=\"signature-toolbar\">\r\n <div class=\"toolbar-section\">\r\n <NButtonGroup>\r\n <NButton\r\n :type=\"currentMode === 'pen' ? 'primary' : 'default'\"\r\n size=\"small\"\r\n @click=\"currentMode = 'pen'\"\r\n >\r\n <template #icon>\r\n <C_Icon name=\"mdi:draw\" :size=\"16\" color=\"currentColor\" />\r\n </template>\r\n 画笔\r\n </NButton>\r\n <NButton\r\n :type=\"currentMode === 'eraser' ? 'primary' : 'default'\"\r\n size=\"small\"\r\n @click=\"currentMode = 'eraser'\"\r\n >\r\n <template #icon>\r\n <C_Icon name=\"mdi:eraser\" :size=\"16\" color=\"currentColor\" />\r\n </template>\r\n 橡皮擦\r\n </NButton>\r\n </NButtonGroup>\r\n </div>\r\n\r\n <div class=\"toolbar-section divider\" />\r\n\r\n <div v-if=\"currentMode === 'pen'\" class=\"toolbar-section\">\r\n <span class=\"section-label\">颜色</span>\r\n <NColorPicker\r\n v-model:value=\"currentPenConfig.color\"\r\n :show-alpha=\"false\"\r\n size=\"small\"\r\n :swatches=\"PRESET_COLORS\"\r\n />\r\n </div>\r\n\r\n <div v-if=\"currentMode === 'pen'\" class=\"toolbar-section\">\r\n <span class=\"section-label\">粗细</span>\r\n <NInputNumber\r\n v-model:value=\"currentPenConfig.width\"\r\n :min=\"1\"\r\n :max=\"20\"\r\n size=\"small\"\r\n style=\"width: 80px\"\r\n />\r\n </div>\r\n\r\n <div class=\"toolbar-section divider\" />\r\n\r\n <div class=\"toolbar-section\">\r\n <NButton size=\"small\" :disabled=\"!canUndo\" @click=\"handleUndo\">\r\n <template #icon>\r\n <C_Icon name=\"mdi:undo\" :size=\"16\" color=\"currentColor\" />\r\n </template>\r\n 撤销\r\n </NButton>\r\n <NButton size=\"small\" :disabled=\"!canRedo\" @click=\"handleRedo\">\r\n <template #icon>\r\n <C_Icon name=\"mdi:redo\" :size=\"16\" color=\"currentColor\" />\r\n </template>\r\n 重做\r\n </NButton>\r\n </div>\r\n\r\n <div class=\"toolbar-section divider\" />\r\n\r\n <div class=\"toolbar-section\">\r\n <NButton\r\n size=\"small\"\r\n type=\"error\"\r\n :disabled=\"isEmpty\"\r\n @click=\"handleClear\"\r\n >\r\n <template #icon>\r\n <C_Icon name=\"mdi:delete-outline\" :size=\"16\" color=\"currentColor\" />\r\n </template>\r\n 清空\r\n </NButton>\r\n </div>\r\n </div>\r\n\r\n <div\r\n class=\"signature-canvas-wrapper\"\r\n :class=\"{ disabled, readonly }\"\r\n :style=\"{\r\n width: typeof width === 'number' ? `${width}px` : width,\r\n height: typeof height === 'number' ? `${height}px` : height,\r\n backgroundColor: backgroundColor || 'transparent',\r\n }\"\r\n >\r\n <canvas\r\n ref=\"canvasRef\"\r\n class=\"signature-canvas\"\r\n :class=\"{ disabled, readonly }\"\r\n />\r\n <div v-if=\"isEmpty && !disabled && !readonly\" class=\"canvas-placeholder\">\r\n 请在此处签名\r\n </div>\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref, reactive, toRef, onMounted, onUnmounted } from \"vue\";\r\nimport { NButton, NButtonGroup, NColorPicker, NInputNumber } from \"naive-ui\";\r\nimport C_Icon from \"../C_Icon/index.vue\";\r\nimport { useSignatureCanvas } from \"./composables/useSignatureCanvas\";\r\nimport { useSignatureHistory } from \"./composables/useSignatureHistory\";\r\nimport { useSignatureExport } from \"./composables/useSignatureExport\";\r\nimport {\r\n DEFAULT_PEN_CONFIG,\r\n DEFAULT_WATERMARK_CONFIG,\r\n PRESET_COLORS,\r\n} from \"./data\";\r\nimport type {\r\n ExportOptions,\r\n PenConfig,\r\n PenMode,\r\n SignatureExpose,\r\n SignaturePoint,\r\n SignatureProps,\r\n SignatureStroke,\r\n WatermarkConfig,\r\n} from \"./types\";\r\n\r\ndefineOptions({ name: \"C_Signature\" });\r\n\r\nconst props = withDefaults(defineProps<SignatureProps>(), {\r\n width: \"100%\",\r\n height: 300,\r\n disabled: false,\r\n readonly: false,\r\n showToolbar: true,\r\n maxHistory: 50,\r\n});\r\n\r\nconst emit = defineEmits<{\r\n \"start-draw\": [];\r\n drawing: [point: SignaturePoint];\r\n \"end-draw\": [stroke: SignatureStroke];\r\n clear: [];\r\n undo: [];\r\n redo: [];\r\n change: [data: SignatureStroke[]];\r\n}>();\r\n\r\nconst canvasRef = ref<HTMLCanvasElement | null>(null);\r\nconst currentMode = ref<PenMode>(\"pen\");\r\nconst currentPenConfig = reactive<PenConfig>({\r\n ...DEFAULT_PEN_CONFIG,\r\n ...props.penConfig,\r\n});\r\nconst currentWatermark = reactive<WatermarkConfig>({\r\n ...DEFAULT_WATERMARK_CONFIG,\r\n ...props.watermark,\r\n});\r\n\r\nconst {\r\n strokes,\r\n canUndo,\r\n canRedo,\r\n isEmpty,\r\n addStroke,\r\n undo,\r\n redo,\r\n clear,\r\n loadData,\r\n} = useSignatureHistory({\r\n maxHistory: props.maxHistory,\r\n onChange: (data) => {\r\n canvasInstance.redrawStrokes(data as SignatureStroke[]);\r\n emit(\"change\", data as SignatureStroke[]);\r\n },\r\n});\r\n\r\nconst canvasInstance = useSignatureCanvas({\r\n canvasRef,\r\n penConfig: toRef(currentPenConfig),\r\n mode: currentMode,\r\n disabled: toRef(props, \"disabled\"),\r\n onStrokeComplete: (stroke: SignatureStroke) => {\r\n addStroke(stroke);\r\n emit(\"end-draw\", stroke);\r\n },\r\n onDrawStart: () => emit(\"start-draw\"),\r\n onDrawing: (point: SignaturePoint) => emit(\"drawing\", point),\r\n});\r\n\r\nconst exportInstance = useSignatureExport({\r\n canvasRef,\r\n watermark: toRef(currentWatermark),\r\n});\r\n\r\nconst handleUndo = (): boolean => {\r\n const result = undo();\r\n if (result) emit(\"undo\");\r\n return result;\r\n};\r\n\r\nconst handleRedo = (): boolean => {\r\n const result = redo();\r\n if (result) emit(\"redo\");\r\n return result;\r\n};\r\n\r\nconst handleClear = () => {\r\n clear();\r\n canvasInstance.clearCanvas();\r\n emit(\"clear\");\r\n};\r\n\r\nconst exportSignature = async (\r\n options?: ExportOptions,\r\n): Promise<string | Blob> => {\r\n return exportInstance.exportSignature(options);\r\n};\r\n\r\nconst download = async (\r\n filename?: string,\r\n options?: ExportOptions,\r\n): Promise<void> => {\r\n return exportInstance.download(filename, options);\r\n};\r\n\r\nconst loadImage = async (imageUrl: string): Promise<void> => {\r\n await exportInstance.loadImage(imageUrl);\r\n clear();\r\n};\r\n\r\nconst getSignatureData = (): SignatureStroke[] =>\r\n strokes.value as SignatureStroke[];\r\nconst loadSignatureData = (data: SignatureStroke[]): void => loadData(data);\r\nconst isSignatureEmpty = (): boolean => isEmpty.value;\r\n\r\nonMounted(() => {\r\n canvasInstance.initCanvas();\r\n canvasInstance.bindEvents();\r\n if (props.backgroundImage) loadImage(props.backgroundImage);\r\n});\r\n\r\nonUnmounted(() => canvasInstance.unbindEvents());\r\n\r\ndefineExpose<SignatureExpose>({\r\n clear: handleClear,\r\n undo: handleUndo,\r\n redo: handleRedo,\r\n export: exportSignature,\r\n download,\r\n loadImage,\r\n getSignatureData,\r\n loadSignatureData,\r\n isEmpty: isSignatureEmpty,\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: 2026-02-25\r\n * @Description: 电子签名组件\r\n * @Migration: naive-ui-components 组件库迁移版本\r\n * Copyright (c) 2026 by CHENY, All Rights Reserved.\r\n-->\r\n<template>\r\n <div class=\"c-signature\">\r\n <div v-if=\"showToolbar\" class=\"signature-toolbar\">\r\n <div class=\"toolbar-section\">\r\n <NButtonGroup>\r\n <NButton\r\n :type=\"currentMode === 'pen' ? 'primary' : 'default'\"\r\n size=\"small\"\r\n @click=\"currentMode = 'pen'\"\r\n >\r\n <template #icon>\r\n <C_Icon name=\"mdi:draw\" :size=\"16\" color=\"currentColor\" />\r\n </template>\r\n 画笔\r\n </NButton>\r\n <NButton\r\n :type=\"currentMode === 'eraser' ? 'primary' : 'default'\"\r\n size=\"small\"\r\n @click=\"currentMode = 'eraser'\"\r\n >\r\n <template #icon>\r\n <C_Icon name=\"mdi:eraser\" :size=\"16\" color=\"currentColor\" />\r\n </template>\r\n 橡皮擦\r\n </NButton>\r\n </NButtonGroup>\r\n </div>\r\n\r\n <div class=\"toolbar-section divider\" />\r\n\r\n <div v-if=\"currentMode === 'pen'\" class=\"toolbar-section\">\r\n <span class=\"section-label\">颜色</span>\r\n <NColorPicker\r\n v-model:value=\"currentPenConfig.color\"\r\n :show-alpha=\"false\"\r\n size=\"small\"\r\n :swatches=\"PRESET_COLORS\"\r\n />\r\n </div>\r\n\r\n <div v-if=\"currentMode === 'pen'\" class=\"toolbar-section\">\r\n <span class=\"section-label\">粗细</span>\r\n <NInputNumber\r\n v-model:value=\"currentPenConfig.width\"\r\n :min=\"1\"\r\n :max=\"20\"\r\n size=\"small\"\r\n style=\"width: 80px\"\r\n />\r\n </div>\r\n\r\n <div class=\"toolbar-section divider\" />\r\n\r\n <div class=\"toolbar-section\">\r\n <NButton size=\"small\" :disabled=\"!canUndo\" @click=\"handleUndo\">\r\n <template #icon>\r\n <C_Icon name=\"mdi:undo\" :size=\"16\" color=\"currentColor\" />\r\n </template>\r\n 撤销\r\n </NButton>\r\n <NButton size=\"small\" :disabled=\"!canRedo\" @click=\"handleRedo\">\r\n <template #icon>\r\n <C_Icon name=\"mdi:redo\" :size=\"16\" color=\"currentColor\" />\r\n </template>\r\n 重做\r\n </NButton>\r\n </div>\r\n\r\n <div class=\"toolbar-section divider\" />\r\n\r\n <div class=\"toolbar-section\">\r\n <NButton\r\n size=\"small\"\r\n type=\"error\"\r\n :disabled=\"isEmpty\"\r\n @click=\"handleClear\"\r\n >\r\n <template #icon>\r\n <C_Icon name=\"mdi:delete-outline\" :size=\"16\" color=\"currentColor\" />\r\n </template>\r\n 清空\r\n </NButton>\r\n </div>\r\n </div>\r\n\r\n <div\r\n class=\"signature-canvas-wrapper\"\r\n :class=\"{ disabled, readonly }\"\r\n :style=\"{\r\n width: typeof width === 'number' ? `${width}px` : width,\r\n height: typeof height === 'number' ? `${height}px` : height,\r\n backgroundColor: backgroundColor || 'transparent',\r\n }\"\r\n >\r\n <canvas\r\n ref=\"canvasRef\"\r\n class=\"signature-canvas\"\r\n :class=\"{ disabled, readonly }\"\r\n />\r\n <div v-if=\"isEmpty && !disabled && !readonly\" class=\"canvas-placeholder\">\r\n 请在此处签名\r\n </div>\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref, reactive, toRef, onMounted, onUnmounted } from \"vue\";\r\nimport { NButton, NButtonGroup, NColorPicker, NInputNumber } from \"naive-ui\";\r\nimport C_Icon from \"../C_Icon/index.vue\";\r\nimport { useSignatureCanvas } from \"./composables/useSignatureCanvas\";\r\nimport { useSignatureHistory } from \"./composables/useSignatureHistory\";\r\nimport { useSignatureExport } from \"./composables/useSignatureExport\";\r\nimport {\r\n DEFAULT_PEN_CONFIG,\r\n DEFAULT_WATERMARK_CONFIG,\r\n PRESET_COLORS,\r\n} from \"./data\";\r\nimport type {\r\n ExportOptions,\r\n PenConfig,\r\n PenMode,\r\n SignatureExpose,\r\n SignaturePoint,\r\n SignatureProps,\r\n SignatureStroke,\r\n WatermarkConfig,\r\n} from \"./types\";\r\n\r\ndefineOptions({ name: \"C_Signature\" });\r\n\r\nconst props = withDefaults(defineProps<SignatureProps>(), {\r\n width: \"100%\",\r\n height: 300,\r\n disabled: false,\r\n readonly: false,\r\n showToolbar: true,\r\n maxHistory: 50,\r\n});\r\n\r\nconst emit = defineEmits<{\r\n \"start-draw\": [];\r\n drawing: [point: SignaturePoint];\r\n \"end-draw\": [stroke: SignatureStroke];\r\n clear: [];\r\n undo: [];\r\n redo: [];\r\n change: [data: SignatureStroke[]];\r\n}>();\r\n\r\nconst canvasRef = ref<HTMLCanvasElement | null>(null);\r\nconst currentMode = ref<PenMode>(\"pen\");\r\nconst currentPenConfig = reactive<PenConfig>({\r\n ...DEFAULT_PEN_CONFIG,\r\n ...props.penConfig,\r\n});\r\nconst currentWatermark = reactive<WatermarkConfig>({\r\n ...DEFAULT_WATERMARK_CONFIG,\r\n ...props.watermark,\r\n});\r\n\r\nconst {\r\n strokes,\r\n canUndo,\r\n canRedo,\r\n isEmpty,\r\n addStroke,\r\n undo,\r\n redo,\r\n clear,\r\n loadData,\r\n} = useSignatureHistory({\r\n maxHistory: props.maxHistory,\r\n onChange: (data) => {\r\n canvasInstance.redrawStrokes(data as SignatureStroke[]);\r\n emit(\"change\", data as SignatureStroke[]);\r\n },\r\n});\r\n\r\nconst canvasInstance = useSignatureCanvas({\r\n canvasRef,\r\n penConfig: toRef(currentPenConfig),\r\n mode: currentMode,\r\n disabled: toRef(props, \"disabled\"),\r\n onStrokeComplete: (stroke: SignatureStroke) => {\r\n addStroke(stroke);\r\n emit(\"end-draw\", stroke);\r\n },\r\n onDrawStart: () => emit(\"start-draw\"),\r\n onDrawing: (point: SignaturePoint) => emit(\"drawing\", point),\r\n});\r\n\r\nconst exportInstance = useSignatureExport({\r\n canvasRef,\r\n watermark: toRef(currentWatermark),\r\n});\r\n\r\nconst handleUndo = (): boolean => {\r\n const result = undo();\r\n if (result) emit(\"undo\");\r\n return result;\r\n};\r\n\r\nconst handleRedo = (): boolean => {\r\n const result = redo();\r\n if (result) emit(\"redo\");\r\n return result;\r\n};\r\n\r\nconst handleClear = () => {\r\n clear();\r\n canvasInstance.clearCanvas();\r\n emit(\"clear\");\r\n};\r\n\r\nconst exportSignature = async (\r\n options?: ExportOptions,\r\n): Promise<string | Blob> => {\r\n return exportInstance.exportSignature(options);\r\n};\r\n\r\nconst download = async (\r\n filename?: string,\r\n options?: ExportOptions,\r\n): Promise<void> => {\r\n return exportInstance.download(filename, options);\r\n};\r\n\r\nconst loadImage = async (imageUrl: string): Promise<void> => {\r\n await exportInstance.loadImage(imageUrl);\r\n clear();\r\n};\r\n\r\nconst getSignatureData = (): SignatureStroke[] =>\r\n strokes.value as SignatureStroke[];\r\nconst loadSignatureData = (data: SignatureStroke[]): void => loadData(data);\r\nconst isSignatureEmpty = (): boolean => isEmpty.value;\r\n\r\nonMounted(() => {\r\n canvasInstance.initCanvas();\r\n canvasInstance.bindEvents();\r\n if (props.backgroundImage) loadImage(props.backgroundImage);\r\n});\r\n\r\nonUnmounted(() => canvasInstance.unbindEvents());\r\n\r\ndefineExpose<SignatureExpose>({\r\n clear: handleClear,\r\n undo: handleUndo,\r\n redo: handleRedo,\r\n export: exportSignature,\r\n download,\r\n loadImage,\r\n getSignatureData,\r\n loadSignatureData,\r\n isEmpty: isSignatureEmpty,\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_Signature.js","names":[],"sources":["../src/components/C_Signature/composables/useSignatureCanvas.ts","../src/components/C_Signature/composables/useSignatureHistory.ts","../src/components/C_Signature/composables/useSignatureExport.ts","../src/components/C_Signature/data.ts","../src/components/C_Signature/index.vue"],"sourcesContent":["import type { Ref } from \"vue\";\r\nimport { ref, readonly } from \"vue\";\r\nimport type {\r\n PenConfig,\r\n PenMode,\r\n SignaturePoint,\r\n SignatureStroke,\r\n} from \"../types\";\r\n\r\ninterface UseSignatureCanvasOptions {\r\n canvasRef: Ref<HTMLCanvasElement | null>;\r\n penConfig: Ref<PenConfig>;\r\n mode: Ref<PenMode>;\r\n disabled: Ref<boolean>;\r\n onStrokeComplete: (stroke: SignatureStroke) => void;\r\n onDrawStart: () => void;\r\n onDrawing: (point: SignaturePoint) => void;\r\n}\r\n\r\nexport function useSignatureCanvas(options: UseSignatureCanvasOptions) {\r\n const {\r\n canvasRef,\r\n penConfig,\r\n mode,\r\n disabled,\r\n onStrokeComplete,\r\n onDrawStart,\r\n onDrawing,\r\n } = options;\r\n\r\n const isDrawing = ref(false);\r\n const currentStroke = ref<SignaturePoint[]>([]);\r\n let ctx: CanvasRenderingContext2D | null = null;\r\n\r\n const initCanvas = () => {\r\n const canvas = canvasRef.value;\r\n if (!canvas) return;\r\n ctx = canvas.getContext(\"2d\", { willReadFrequently: true });\r\n if (!ctx) return;\r\n const dpr = window.devicePixelRatio || 1;\r\n const rect = canvas.getBoundingClientRect();\r\n canvas.width = rect.width * dpr;\r\n canvas.height = rect.height * dpr;\r\n canvas.style.width = `${rect.width}px`;\r\n canvas.style.height = `${rect.height}px`;\r\n ctx.scale(dpr, dpr);\r\n ctx.lineCap = \"round\";\r\n ctx.lineJoin = \"round\";\r\n };\r\n\r\n const getPointFromEvent = (e: MouseEvent | TouchEvent): SignaturePoint => {\r\n const canvas = canvasRef.value;\r\n if (!canvas) return { x: 0, y: 0 };\r\n const rect = canvas.getBoundingClientRect();\r\n let clientX: number;\r\n let clientY: number;\r\n if (\"touches\" in e && e.touches.length > 0) {\r\n ({ clientX, clientY } = e.touches[0]);\r\n } else if (\"clientX\" in e) {\r\n ({ clientX, clientY } = e);\r\n } else {\r\n return { x: 0, y: 0 };\r\n }\r\n return {\r\n x: clientX - rect.left,\r\n y: clientY - rect.top,\r\n timestamp: Date.now(),\r\n };\r\n };\r\n\r\n const drawStroke = (\r\n from: SignaturePoint,\r\n to: SignaturePoint,\r\n config: PenConfig,\r\n eraserMode = false,\r\n ) => {\r\n if (!ctx) return;\r\n ctx.save();\r\n if (eraserMode) {\r\n ctx.globalCompositeOperation = \"destination-out\";\r\n ctx.lineWidth = 20;\r\n } else {\r\n ctx.globalCompositeOperation = \"source-over\";\r\n ctx.strokeStyle = config.color;\r\n ctx.lineWidth = config.width;\r\n ctx.globalAlpha = config.opacity;\r\n }\r\n ctx.beginPath();\r\n ctx.moveTo(from.x, from.y);\r\n ctx.lineTo(to.x, to.y);\r\n ctx.stroke();\r\n ctx.restore();\r\n };\r\n\r\n const startDrawing = (e: MouseEvent | TouchEvent) => {\r\n if (disabled.value) return;\r\n e.preventDefault();\r\n isDrawing.value = true;\r\n currentStroke.value = [];\r\n const point = getPointFromEvent(e);\r\n currentStroke.value.push(point);\r\n onDrawStart();\r\n };\r\n\r\n const draw = (e: MouseEvent | TouchEvent) => {\r\n if (!isDrawing.value || disabled.value) return;\r\n e.preventDefault();\r\n const point = getPointFromEvent(e);\r\n const lastPoint = currentStroke.value[currentStroke.value.length - 1];\r\n if (lastPoint) {\r\n drawStroke(lastPoint, point, penConfig.value, mode.value === \"eraser\");\r\n }\r\n currentStroke.value.push(point);\r\n onDrawing(point);\r\n };\r\n\r\n const endDrawing = (e: MouseEvent | TouchEvent) => {\r\n if (!isDrawing.value || disabled.value) return;\r\n e.preventDefault();\r\n isDrawing.value = false;\r\n if (currentStroke.value.length > 0) {\r\n const stroke: SignatureStroke = {\r\n points: [...currentStroke.value],\r\n color: penConfig.value.color,\r\n width: penConfig.value.width,\r\n opacity: penConfig.value.opacity,\r\n mode: mode.value,\r\n };\r\n onStrokeComplete(stroke);\r\n currentStroke.value = [];\r\n }\r\n };\r\n\r\n const redrawStrokes = (strokes: SignatureStroke[]) => {\r\n if (!ctx || !canvasRef.value) return;\r\n const canvas = canvasRef.value;\r\n ctx.clearRect(0, 0, canvas.width, canvas.height);\r\n strokes.forEach((stroke) => {\r\n for (let i = 1; i < stroke.points.length; i++) {\r\n drawStroke(\r\n stroke.points[i - 1],\r\n stroke.points[i],\r\n { color: stroke.color, width: stroke.width, opacity: stroke.opacity },\r\n stroke.mode === \"eraser\",\r\n );\r\n }\r\n });\r\n };\r\n\r\n const clearCanvas = () => {\r\n if (!ctx || !canvasRef.value) return;\r\n ctx.clearRect(0, 0, canvasRef.value.width, canvasRef.value.height);\r\n };\r\n\r\n const bindEvents = () => {\r\n const canvas = canvasRef.value;\r\n if (!canvas) return;\r\n canvas.addEventListener(\"mousedown\", startDrawing);\r\n canvas.addEventListener(\"mousemove\", draw);\r\n canvas.addEventListener(\"mouseup\", endDrawing);\r\n canvas.addEventListener(\"mouseleave\", endDrawing);\r\n canvas.addEventListener(\"touchstart\", startDrawing, { passive: false });\r\n canvas.addEventListener(\"touchmove\", draw, { passive: false });\r\n canvas.addEventListener(\"touchend\", endDrawing);\r\n canvas.addEventListener(\"touchcancel\", endDrawing);\r\n };\r\n\r\n const unbindEvents = () => {\r\n const canvas = canvasRef.value;\r\n if (!canvas) return;\r\n canvas.removeEventListener(\"mousedown\", startDrawing);\r\n canvas.removeEventListener(\"mousemove\", draw);\r\n canvas.removeEventListener(\"mouseup\", endDrawing);\r\n canvas.removeEventListener(\"mouseleave\", endDrawing);\r\n canvas.removeEventListener(\"touchstart\", startDrawing);\r\n canvas.removeEventListener(\"touchmove\", draw);\r\n canvas.removeEventListener(\"touchend\", endDrawing);\r\n canvas.removeEventListener(\"touchcancel\", endDrawing);\r\n };\r\n\r\n return {\r\n isDrawing: readonly(isDrawing),\r\n initCanvas,\r\n bindEvents,\r\n unbindEvents,\r\n redrawStrokes,\r\n clearCanvas,\r\n };\r\n}\r\n","import { ref, computed, readonly } from \"vue\";\r\nimport type { SignatureStroke } from \"../types\";\r\n\r\ninterface UseSignatureHistoryOptions {\r\n maxHistory?: number;\r\n onChange?: (strokes: SignatureStroke[]) => void;\r\n}\r\n\r\nexport function useSignatureHistory(options: UseSignatureHistoryOptions = {}) {\r\n const { maxHistory = 50, onChange } = options;\r\n\r\n const strokes = ref<SignatureStroke[]>([]);\r\n const historyStack = ref<SignatureStroke[][]>([]);\r\n const historyIndex = ref(-1);\r\n\r\n const canUndo = computed(() => historyIndex.value > 0);\r\n const canRedo = computed(\r\n () => historyIndex.value < historyStack.value.length - 1,\r\n );\r\n\r\n const addStroke = (stroke: SignatureStroke) => {\r\n strokes.value.push(stroke);\r\n saveToHistory();\r\n };\r\n\r\n const saveToHistory = () => {\r\n historyStack.value = historyStack.value.slice(0, historyIndex.value + 1);\r\n historyStack.value.push([...strokes.value]);\r\n historyIndex.value++;\r\n if (historyStack.value.length > maxHistory) {\r\n historyStack.value.shift();\r\n historyIndex.value--;\r\n }\r\n onChange?.(strokes.value);\r\n };\r\n\r\n const undo = (): boolean => {\r\n if (!canUndo.value) return false;\r\n historyIndex.value--;\r\n strokes.value = [...historyStack.value[historyIndex.value]];\r\n onChange?.(strokes.value);\r\n return true;\r\n };\r\n\r\n const redo = (): boolean => {\r\n if (!canRedo.value) return false;\r\n historyIndex.value++;\r\n strokes.value = [...historyStack.value[historyIndex.value]];\r\n onChange?.(strokes.value);\r\n return true;\r\n };\r\n\r\n const clear = () => {\r\n strokes.value = [];\r\n historyStack.value = [[]];\r\n historyIndex.value = 0;\r\n onChange?.(strokes.value);\r\n };\r\n\r\n const loadData = (data: SignatureStroke[]) => {\r\n strokes.value = [...data];\r\n historyStack.value = [[...data]];\r\n historyIndex.value = 0;\r\n onChange?.(strokes.value);\r\n };\r\n\r\n const isEmpty = computed(() => strokes.value.length === 0);\r\n\r\n // 初始化历史栈\r\n historyStack.value = [[]];\r\n historyIndex.value = 0;\r\n\r\n return {\r\n strokes: readonly(strokes),\r\n canUndo: readonly(canUndo),\r\n canRedo: readonly(canRedo),\r\n isEmpty: readonly(isEmpty),\r\n addStroke,\r\n undo,\r\n redo,\r\n clear,\r\n loadData,\r\n };\r\n}\r\n","import type { Ref } from 'vue'\nimport type { ExportOptions, WatermarkConfig } from '../types'\n\ninterface UseSignatureExportOptions {\n canvasRef: Ref<HTMLCanvasElement | null>\n watermark?: Ref<Partial<WatermarkConfig>>\n}\n\n/**\n *\n */\nexport function useSignatureExport(options: UseSignatureExportOptions) {\n const { canvasRef, watermark } = options\n\n const getWatermarkPosition = (\n canvas: HTMLCanvasElement,\n textWidth: number,\n fontSize: number,\n position: string\n ): { x: number; y: number } => {\n const padding = 10\n const positions = {\n 'top-left': { x: padding, y: fontSize + padding },\n 'top-right': {\n x: canvas.width - textWidth - padding,\n y: fontSize + padding,\n },\n 'bottom-left': { x: padding, y: canvas.height - padding },\n 'bottom-right': {\n x: canvas.width - textWidth - padding,\n y: canvas.height - padding,\n },\n }\n return (\n positions[position as keyof typeof positions] || positions['bottom-right']\n )\n }\n\n const drawWatermark = (canvas: HTMLCanvasElement, text: string): void => {\n const ctx = canvas.getContext('2d')\n if (!ctx || !watermark?.value?.show) return\n const config = {\n fontSize: watermark.value.fontSize || 12,\n color: watermark.value.color || '#999999',\n position: watermark.value.position || 'bottom-right',\n }\n ctx.save()\n ctx.font = `${config.fontSize}px Arial`\n ctx.fillStyle = config.color\n ctx.textBaseline = 'bottom'\n const textWidth = ctx.measureText(text).width\n const { x, y } = getWatermarkPosition(\n canvas,\n textWidth,\n config.fontSize,\n config.position\n )\n ctx.fillText(text, x, y)\n ctx.restore()\n }\n\n const createTempCanvas = (\n sourceCanvas: HTMLCanvasElement,\n includeBackground: boolean,\n backgroundColor: string\n ) => {\n const tempCanvas = document.createElement('canvas')\n tempCanvas.width = sourceCanvas.width\n tempCanvas.height = sourceCanvas.height\n const tempCtx = tempCanvas.getContext('2d')\n if (!tempCtx) throw new Error('无法创建临时 Canvas')\n if (includeBackground) {\n tempCtx.fillStyle = backgroundColor\n tempCtx.fillRect(0, 0, tempCanvas.width, tempCanvas.height)\n }\n tempCtx.drawImage(sourceCanvas, 0, 0)\n return { canvas: tempCanvas, ctx: tempCtx }\n }\n\n const prepareExportCanvas = (\n canvas: HTMLCanvasElement,\n options: ExportOptions\n ): HTMLCanvasElement => {\n const {\n includeBackground = false,\n backgroundColor = '#FFFFFF',\n includeWatermark = false,\n } = options\n const { canvas: tempCanvas } = createTempCanvas(\n canvas,\n includeBackground,\n backgroundColor\n )\n // includeWatermark 为 true 时才叠加水印,无视 watermark.show 的状态\n // 这样「不含水印导出」即使组件配置了水印也不会叠加\n if (includeWatermark && watermark?.value?.text) {\n drawWatermark(tempCanvas, watermark.value.text)\n }\n return tempCanvas\n }\n\n const exportToBlob = (\n canvas: HTMLCanvasElement,\n quality: number\n ): Promise<Blob> => {\n return new Promise<Blob>((resolve, reject) => {\n canvas.toBlob(\n blob => (blob ? resolve(blob) : reject(new Error('导出失败'))),\n 'image/png',\n quality\n )\n })\n }\n\n const isCanvasEmpty = (canvas: HTMLCanvasElement): boolean => {\n const ctx = canvas.getContext('2d')\n if (!ctx) return true\n const { data } = ctx.getImageData(0, 0, canvas.width, canvas.height)\n return !data.some(v => v !== 0)\n }\n\n const exportSignature = async (\n options: ExportOptions = {}\n ): Promise<string | Blob> => {\n const canvas = canvasRef.value\n if (!canvas) throw new Error('Canvas 未初始化')\n if (isCanvasEmpty(canvas)) throw new Error('签名为空,请先签名后再导出')\n const { format = 'png', quality = 0.92 } = options\n if (format === 'svg') {\n return 'data:image/svg+xml;charset=utf-8,<svg xmlns=\"http://www.w3.org/2000/svg\"><text>SVG export placeholder</text></svg>'\n }\n const tempCanvas = prepareExportCanvas(canvas, options)\n if (format === 'blob') return exportToBlob(tempCanvas, quality)\n const mimeType = format === 'jpeg' ? 'image/jpeg' : 'image/png'\n return tempCanvas.toDataURL(mimeType, quality)\n }\n\n const download = async (\n filename = 'signature',\n options: ExportOptions = {}\n ): Promise<void> => {\n const format = options.format || 'png'\n const result = await exportSignature({ ...options, format })\n if (result instanceof Blob) {\n const url = URL.createObjectURL(result)\n const link = document.createElement('a')\n link.href = url\n link.download = `${filename}.${format}`\n link.click()\n URL.revokeObjectURL(url)\n } else if (typeof result === 'string') {\n const link = document.createElement('a')\n link.href = result\n link.download = `${filename}.${format}`\n link.click()\n }\n }\n\n const loadImage = async (imageUrl: string): Promise<void> => {\n const canvas = canvasRef.value\n if (!canvas) throw new Error('Canvas 未初始化')\n const ctx = canvas.getContext('2d')\n if (!ctx) throw new Error('无法获取 Canvas 上下文')\n return new Promise((resolve, reject) => {\n const img = new Image()\n img.crossOrigin = 'anonymous'\n img.onload = () => {\n ctx.clearRect(0, 0, canvas.width, canvas.height)\n ctx.drawImage(img, 0, 0, canvas.width, canvas.height)\n resolve()\n }\n img.onerror = () => reject(new Error(`图片加载失败: ${imageUrl}`))\n img.src = imageUrl\n })\n }\n\n return { exportSignature, download, loadImage }\n}\n","import type { EraserConfig, PenConfig, WatermarkConfig } from \"./types\";\r\n\r\nexport const DEFAULT_PEN_CONFIG: PenConfig = {\r\n color: \"#000000\",\r\n width: 2,\r\n opacity: 1,\r\n};\r\n\r\nexport const DEFAULT_ERASER_CONFIG: EraserConfig = { size: 20 };\r\n\r\nexport const DEFAULT_WATERMARK_CONFIG: WatermarkConfig = {\r\n show: false,\r\n text: \"\",\r\n fontSize: 12,\r\n color: \"#999999\",\r\n position: \"bottom-right\",\r\n};\r\n\r\nexport const PRESET_COLORS = [\r\n \"#000000\",\r\n \"#FF0000\",\r\n \"#0000FF\",\r\n \"#00AA00\",\r\n \"#FF6600\",\r\n \"#9900FF\",\r\n];\r\n\r\nexport const PRESET_WIDTHS = [1, 2, 3, 5, 8];\r\n\r\nexport const EXPORT_FORMAT_OPTIONS = [\r\n { label: \"PNG\", value: \"png\" },\r\n { label: \"JPEG\", value: \"jpeg\" },\r\n { label: \"SVG\", value: \"svg\" },\r\n { label: \"Blob\", value: \"blob\" },\r\n] as const;\r\n\r\nexport const WATERMARK_POSITION_OPTIONS = [\r\n { label: \"左上\", value: \"top-left\" },\r\n { label: \"右上\", value: \"top-right\" },\r\n { label: \"左下\", value: \"bottom-left\" },\r\n { label: \"右下\", value: \"bottom-right\" },\r\n] as const;\r\n","<!--\n * @Author: ChenYu ycyplus@gmail.com\n * @Date: 2026-02-25\n * @Description: 电子签名组件\n * @Migration: naive-ui-components 组件库迁移版本\n * Copyright (c) 2026 by CHENY, All Rights Reserved.\n-->\n<template>\n <div class=\"c-signature\">\n <div v-if=\"showToolbar\" class=\"signature-toolbar\">\n <div class=\"toolbar-section\">\n <NButtonGroup>\n <NButton\n :type=\"currentMode === 'pen' ? 'primary' : 'default'\"\n size=\"small\"\n @click=\"currentMode = 'pen'\"\n >\n <template #icon>\n <C_Icon name=\"mdi:draw\" :size=\"16\" color=\"currentColor\" />\n </template>\n 画笔\n </NButton>\n <NButton\n :type=\"currentMode === 'eraser' ? 'primary' : 'default'\"\n size=\"small\"\n @click=\"currentMode = 'eraser'\"\n >\n <template #icon>\n <C_Icon name=\"mdi:eraser\" :size=\"16\" color=\"currentColor\" />\n </template>\n 橡皮擦\n </NButton>\n </NButtonGroup>\n </div>\n\n <div class=\"toolbar-section divider\" />\n\n <div v-if=\"currentMode === 'pen'\" class=\"toolbar-section\">\n <span class=\"section-label\">颜色</span>\n <NColorPicker\n v-model:value=\"currentPenConfig.color\"\n :show-alpha=\"false\"\n size=\"small\"\n :swatches=\"PRESET_COLORS\"\n />\n </div>\n\n <div v-if=\"currentMode === 'pen'\" class=\"toolbar-section\">\n <span class=\"section-label\">粗细</span>\n <NInputNumber\n v-model:value=\"currentPenConfig.width\"\n :min=\"1\"\n :max=\"20\"\n size=\"small\"\n style=\"width: 80px\"\n />\n </div>\n\n <div class=\"toolbar-section divider\" />\n\n <div class=\"toolbar-section\">\n <NButton size=\"small\" :disabled=\"!canUndo\" @click=\"handleUndo\">\n <template #icon>\n <C_Icon name=\"mdi:undo\" :size=\"16\" color=\"currentColor\" />\n </template>\n 撤销\n </NButton>\n <NButton size=\"small\" :disabled=\"!canRedo\" @click=\"handleRedo\">\n <template #icon>\n <C_Icon name=\"mdi:redo\" :size=\"16\" color=\"currentColor\" />\n </template>\n 重做\n </NButton>\n </div>\n\n <div class=\"toolbar-section divider\" />\n\n <div class=\"toolbar-section\">\n <NButton\n size=\"small\"\n type=\"error\"\n :disabled=\"isEmpty\"\n @click=\"handleClear\"\n >\n <template #icon>\n <C_Icon name=\"mdi:delete-outline\" :size=\"16\" color=\"currentColor\" />\n </template>\n 清空\n </NButton>\n </div>\n </div>\n\n <div\n class=\"signature-canvas-wrapper\"\n :class=\"{ disabled, readonly }\"\n :style=\"{\n width: typeof width === 'number' ? `${width}px` : width,\n height: typeof height === 'number' ? `${height}px` : height,\n backgroundColor: backgroundColor || 'transparent',\n }\"\n >\n <canvas\n ref=\"canvasRef\"\n class=\"signature-canvas\"\n :class=\"{ disabled, readonly }\"\n />\n <div v-if=\"isEmpty && !disabled && !readonly\" class=\"canvas-placeholder\">\n 请在此处签名\n </div>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, reactive, toRef, onMounted, onUnmounted } from \"vue\";\nimport { NButton, NButtonGroup, NColorPicker, NInputNumber } from \"naive-ui\";\nimport C_Icon from \"../C_Icon/index.vue\";\nimport { useSignatureCanvas } from \"./composables/useSignatureCanvas\";\nimport { useSignatureHistory } from \"./composables/useSignatureHistory\";\nimport { useSignatureExport } from \"./composables/useSignatureExport\";\nimport {\n DEFAULT_PEN_CONFIG,\n DEFAULT_WATERMARK_CONFIG,\n PRESET_COLORS,\n} from \"./data\";\nimport type {\n ExportOptions,\n PenConfig,\n PenMode,\n SignatureExpose,\n SignaturePoint,\n SignatureProps,\n SignatureStroke,\n WatermarkConfig,\n} from \"./types\";\n\ndefineOptions({ name: \"C_Signature\" });\n\nconst props = withDefaults(defineProps<SignatureProps>(), {\n width: \"100%\",\n height: 300,\n disabled: false,\n readonly: false,\n showToolbar: true,\n maxHistory: 50,\n});\n\nconst emit = defineEmits<{\n \"start-draw\": [];\n drawing: [point: SignaturePoint];\n \"end-draw\": [stroke: SignatureStroke];\n clear: [];\n undo: [];\n redo: [];\n change: [data: SignatureStroke[]];\n}>();\n\nconst canvasRef = ref<HTMLCanvasElement | null>(null);\nconst currentMode = ref<PenMode>(\"pen\");\nconst currentPenConfig = reactive<PenConfig>({\n ...DEFAULT_PEN_CONFIG,\n ...props.penConfig,\n});\nconst currentWatermark = reactive<WatermarkConfig>({\n ...DEFAULT_WATERMARK_CONFIG,\n ...props.watermark,\n});\n\nconst {\n strokes,\n canUndo,\n canRedo,\n isEmpty,\n addStroke,\n undo,\n redo,\n clear,\n loadData,\n} = useSignatureHistory({\n maxHistory: props.maxHistory,\n onChange: (data) => {\n canvasInstance.redrawStrokes(data as SignatureStroke[]);\n emit(\"change\", data as SignatureStroke[]);\n },\n});\n\nconst canvasInstance = useSignatureCanvas({\n canvasRef,\n penConfig: toRef(currentPenConfig),\n mode: currentMode,\n disabled: toRef(props, \"disabled\"),\n onStrokeComplete: (stroke: SignatureStroke) => {\n addStroke(stroke);\n emit(\"end-draw\", stroke);\n },\n onDrawStart: () => emit(\"start-draw\"),\n onDrawing: (point: SignaturePoint) => emit(\"drawing\", point),\n});\n\nconst exportInstance = useSignatureExport({\n canvasRef,\n watermark: toRef(currentWatermark),\n});\n\nconst handleUndo = (): boolean => {\n const result = undo();\n if (result) emit(\"undo\");\n return result;\n};\n\nconst handleRedo = (): boolean => {\n const result = redo();\n if (result) emit(\"redo\");\n return result;\n};\n\nconst handleClear = () => {\n clear();\n canvasInstance.clearCanvas();\n emit(\"clear\");\n};\n\nconst exportSignature = async (\n options?: ExportOptions,\n): Promise<string | Blob> => {\n return exportInstance.exportSignature(options);\n};\n\nconst download = async (\n filename?: string,\n options?: ExportOptions,\n): Promise<void> => {\n return exportInstance.download(filename, options);\n};\n\nconst loadImage = async (imageUrl: string): Promise<void> => {\n await exportInstance.loadImage(imageUrl);\n clear();\n};\n\nconst getSignatureData = (): SignatureStroke[] =>\n strokes.value as SignatureStroke[];\nconst loadSignatureData = (data: SignatureStroke[]): void => loadData(data);\nconst isSignatureEmpty = (): boolean => isEmpty.value;\n\nonMounted(() => {\n canvasInstance.initCanvas();\n canvasInstance.bindEvents();\n if (props.backgroundImage) loadImage(props.backgroundImage);\n});\n\nonUnmounted(() => canvasInstance.unbindEvents());\n\ndefineExpose<SignatureExpose>({\n clear: handleClear,\n undo: handleUndo,\n redo: handleRedo,\n export: exportSignature,\n download,\n loadImage,\n getSignatureData,\n loadSignatureData,\n isEmpty: isSignatureEmpty,\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,NButtonGroup as r,NColorPicker as i,NInputNumber as a}from"naive-ui";import{computed as o,createCommentVNode as s,createElementBlock as c,createElementVNode as l,createTextVNode as u,createVNode as d,defineComponent as f,normalizeClass as p,normalizeStyle as m,onMounted as h,onUnmounted as g,openBlock as _,reactive as v,readonly as y,ref as b,toRef as x,unref as S,withCtx as C}from"vue";function w(e){let{canvasRef:t,penConfig:n,mode:r,disabled:i,onStrokeComplete:a,onDrawStart:o,onDrawing:s}=e,c=b(!1),l=b([]),u=null,d=()=>{let e=t.value;if(!e||(u=e.getContext(`2d`,{willReadFrequently:!0}),!u))return;let n=window.devicePixelRatio||1,r=e.getBoundingClientRect();e.width=r.width*n,e.height=r.height*n,e.style.width=`${r.width}px`,e.style.height=`${r.height}px`,u.scale(n,n),u.lineCap=`round`,u.lineJoin=`round`},f=e=>{let n=t.value;if(!n)return{x:0,y:0};let r=n.getBoundingClientRect(),i,a;if(`touches`in e&&e.touches.length>0)({clientX:i,clientY:a}=e.touches[0]);else if(`clientX`in e)({clientX:i,clientY:a}=e);else return{x:0,y:0};return{x:i-r.left,y:a-r.top,timestamp:Date.now()}},p=(e,t,n,r=!1)=>{u&&(u.save(),r?(u.globalCompositeOperation=`destination-out`,u.lineWidth=20):(u.globalCompositeOperation=`source-over`,u.strokeStyle=n.color,u.lineWidth=n.width,u.globalAlpha=n.opacity),u.beginPath(),u.moveTo(e.x,e.y),u.lineTo(t.x,t.y),u.stroke(),u.restore())},m=e=>{if(i.value)return;e.preventDefault(),c.value=!0,l.value=[];let t=f(e);l.value.push(t),o()},h=e=>{if(!c.value||i.value)return;e.preventDefault();let t=f(e),a=l.value[l.value.length-1];a&&p(a,t,n.value,r.value===`eraser`),l.value.push(t),s(t)},g=e=>{!c.value||i.value||(e.preventDefault(),c.value=!1,l.value.length>0&&(a({points:[...l.value],color:n.value.color,width:n.value.width,opacity:n.value.opacity,mode:r.value}),l.value=[]))};return{isDrawing:y(c),initCanvas:d,bindEvents:()=>{let e=t.value;e&&(e.addEventListener(`mousedown`,m),e.addEventListener(`mousemove`,h),e.addEventListener(`mouseup`,g),e.addEventListener(`mouseleave`,g),e.addEventListener(`touchstart`,m,{passive:!1}),e.addEventListener(`touchmove`,h,{passive:!1}),e.addEventListener(`touchend`,g),e.addEventListener(`touchcancel`,g))},unbindEvents:()=>{let e=t.value;e&&(e.removeEventListener(`mousedown`,m),e.removeEventListener(`mousemove`,h),e.removeEventListener(`mouseup`,g),e.removeEventListener(`mouseleave`,g),e.removeEventListener(`touchstart`,m),e.removeEventListener(`touchmove`,h),e.removeEventListener(`touchend`,g),e.removeEventListener(`touchcancel`,g))},redrawStrokes:e=>{if(!u||!t.value)return;let n=t.value;u.clearRect(0,0,n.width,n.height),e.forEach(e=>{for(let t=1;t<e.points.length;t++)p(e.points[t-1],e.points[t],{color:e.color,width:e.width,opacity:e.opacity},e.mode===`eraser`)})},clearCanvas:()=>{!u||!t.value||u.clearRect(0,0,t.value.width,t.value.height)}}}function T(e={}){let{maxHistory:t=50,onChange:n}=e,r=b([]),i=b([]),a=b(-1),s=o(()=>a.value>0),c=o(()=>a.value<i.value.length-1),l=e=>{r.value.push(e),u()},u=()=>{i.value=i.value.slice(0,a.value+1),i.value.push([...r.value]),a.value++,i.value.length>t&&(i.value.shift(),a.value--),n?.(r.value)},d=()=>s.value?(a.value--,r.value=[...i.value[a.value]],n?.(r.value),!0):!1,f=()=>c.value?(a.value++,r.value=[...i.value[a.value]],n?.(r.value),!0):!1,p=()=>{r.value=[],i.value=[[]],a.value=0,n?.(r.value)},m=e=>{r.value=[...e],i.value=[[...e]],a.value=0,n?.(r.value)},h=o(()=>r.value.length===0);return i.value=[[]],a.value=0,{strokes:y(r),canUndo:y(s),canRedo:y(c),isEmpty:y(h),addStroke:l,undo:d,redo:f,clear:p,loadData:m}}function E(e){let{canvasRef:t,watermark:n}=e,r=(e,t,n,r)=>{let i={"top-left":{x:10,y:n+10},"top-right":{x:e.width-t-10,y:n+10},"bottom-left":{x:10,y:e.height-10},"bottom-right":{x:e.width-t-10,y:e.height-10}};return i[r]||i[`bottom-right`]},i=(e,t)=>{let i=e.getContext(`2d`);if(!i||!n?.value?.show)return;let a={fontSize:n.value.fontSize||12,color:n.value.color||`#999999`,position:n.value.position||`bottom-right`};i.save(),i.font=`${a.fontSize}px Arial`,i.fillStyle=a.color,i.textBaseline=`bottom`;let o=i.measureText(t).width,{x:s,y:c}=r(e,o,a.fontSize,a.position);i.fillText(t,s,c),i.restore()},a=(e,t,n)=>{let r=document.createElement(`canvas`);r.width=e.width,r.height=e.height;let i=r.getContext(`2d`);if(!i)throw Error(`无法创建临时 Canvas`);return t&&(i.fillStyle=n,i.fillRect(0,0,r.width,r.height)),i.drawImage(e,0,0),{canvas:r,ctx:i}},o=(e,t)=>{let{includeBackground:r=!1,backgroundColor:o=`#FFFFFF`,includeWatermark:s=!1}=t,{canvas:c}=a(e,r,o);return s&&n?.value?.text&&i(c,n.value.text),c},s=(e,t)=>new Promise((n,r)=>{e.toBlob(e=>e?n(e):r(Error(`导出失败`)),`image/png`,t)}),c=e=>{let t=e.getContext(`2d`);if(!t)return!0;let{data:n}=t.getImageData(0,0,e.width,e.height);return!n.some(e=>e!==0)},l=async(e={})=>{let n=t.value;if(!n)throw Error(`Canvas 未初始化`);if(c(n))throw Error(`签名为空,请先签名后再导出`);let{format:r=`png`,quality:i=.92}=e;if(r===`svg`)return`data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg"><text>SVG export placeholder</text></svg>`;let a=o(n,e);if(r===`blob`)return s(a,i);let l=r===`jpeg`?`image/jpeg`:`image/png`;return a.toDataURL(l,i)};return{exportSignature:l,download:async(e=`signature`,t={})=>{let n=t.format||`png`,r=await l({...t,format:n});if(r instanceof Blob){let t=URL.createObjectURL(r),i=document.createElement(`a`);i.href=t,i.download=`${e}.${n}`,i.click(),URL.revokeObjectURL(t)}else if(typeof r==`string`){let t=document.createElement(`a`);t.href=r,t.download=`${e}.${n}`,t.click()}},loadImage:async e=>{let n=t.value;if(!n)throw Error(`Canvas 未初始化`);let r=n.getContext(`2d`);if(!r)throw Error(`无法获取 Canvas 上下文`);return new Promise((t,i)=>{let a=new Image;a.crossOrigin=`anonymous`,a.onload=()=>{r.clearRect(0,0,n.width,n.height),r.drawImage(a,0,0,n.width,n.height),t()},a.onerror=()=>i(Error(`图片加载失败: ${e}`)),a.src=e})}}}const ee={color:`#000000`,width:2,opacity:1},te={show:!1,text:``,fontSize:12,color:`#999999`,position:`bottom-right`},D=[`#000000`,`#FF0000`,`#0000FF`,`#00AA00`,`#FF6600`,`#9900FF`],O={class:`c-signature`},k={key:0,class:`signature-toolbar`},A={class:`toolbar-section`},j={key:0,class:`toolbar-section`},M={key:1,class:`toolbar-section`},N={class:`toolbar-section`},ne={class:`toolbar-section`},re={key:0,class:`canvas-placeholder`};var P=t(f({name:`C_Signature`,__name:`index`,props:{width:{default:`100%`},height:{default:300},penConfig:{},eraserConfig:{},disabled:{type:Boolean,default:!1},readonly:{type:Boolean,default:!1},backgroundImage:{},backgroundColor:{},watermark:{},showToolbar:{type:Boolean,default:!0},maxHistory:{default:50}},emits:[`start-draw`,`drawing`,`end-draw`,`clear`,`undo`,`redo`,`change`],setup(t,{expose:o,emit:f}){let y=t,P=f,F=b(null),I=b(`pen`),L=v({...ee,...y.penConfig}),R=v({...te,...y.watermark}),{strokes:z,canUndo:B,canRedo:V,isEmpty:H,addStroke:U,undo:W,redo:G,clear:K,loadData:q}=T({maxHistory:y.maxHistory,onChange:e=>{J.redrawStrokes(e),P(`change`,e)}}),J=w({canvasRef:F,penConfig:x(L),mode:I,disabled:x(y,`disabled`),onStrokeComplete:e=>{U(e),P(`end-draw`,e)},onDrawStart:()=>P(`start-draw`),onDrawing:e=>P(`drawing`,e)}),Y=E({canvasRef:F,watermark:x(R)}),X=()=>{let e=W();return e&&P(`undo`),e},Z=()=>{let e=G();return e&&P(`redo`),e},Q=()=>{K(),J.clearCanvas(),P(`clear`)},ie=async e=>Y.exportSignature(e),ae=async(e,t)=>Y.download(e,t),$=async e=>{await Y.loadImage(e),K()};return h(()=>{J.initCanvas(),J.bindEvents(),y.backgroundImage&&$(y.backgroundImage)}),g(()=>J.unbindEvents()),o({clear:Q,undo:X,redo:Z,export:ie,download:ae,loadImage:$,getSignatureData:()=>z.value,loadSignatureData:e=>q(e),isEmpty:()=>H.value}),(t,o)=>(_(),c(`div`,O,[t.showToolbar?(_(),c(`div`,k,[l(`div`,A,[d(S(r),null,{default:C(()=>[d(S(n),{type:I.value===`pen`?`primary`:`default`,size:`small`,onClick:o[0]||=e=>I.value=`pen`},{icon:C(()=>[d(e,{name:`mdi:draw`,size:16,color:`currentColor`})]),default:C(()=>[o[4]||=u(` 画笔 `,-1)]),_:1,__:[4]},8,[`type`]),d(S(n),{type:I.value===`eraser`?`primary`:`default`,size:`small`,onClick:o[1]||=e=>I.value=`eraser`},{icon:C(()=>[d(e,{name:`mdi:eraser`,size:16,color:`currentColor`})]),default:C(()=>[o[5]||=u(` 橡皮擦 `,-1)]),_:1,__:[5]},8,[`type`])]),_:1})]),o[11]||=l(`div`,{class:`toolbar-section divider`},null,-1),I.value===`pen`?(_(),c(`div`,j,[o[6]||=l(`span`,{class:`section-label`},`颜色`,-1),d(S(i),{value:L.color,"onUpdate:value":o[2]||=e=>L.color=e,"show-alpha":!1,size:`small`,swatches:S(D)},null,8,[`value`,`swatches`])])):s(`v-if`,!0),I.value===`pen`?(_(),c(`div`,M,[o[7]||=l(`span`,{class:`section-label`},`粗细`,-1),d(S(a),{value:L.width,"onUpdate:value":o[3]||=e=>L.width=e,min:1,max:20,size:`small`,style:{width:`80px`}},null,8,[`value`])])):s(`v-if`,!0),o[12]||=l(`div`,{class:`toolbar-section divider`},null,-1),l(`div`,N,[d(S(n),{size:`small`,disabled:!S(B),onClick:X},{icon:C(()=>[d(e,{name:`mdi:undo`,size:16,color:`currentColor`})]),default:C(()=>[o[8]||=u(` 撤销 `,-1)]),_:1,__:[8]},8,[`disabled`]),d(S(n),{size:`small`,disabled:!S(V),onClick:Z},{icon:C(()=>[d(e,{name:`mdi:redo`,size:16,color:`currentColor`})]),default:C(()=>[o[9]||=u(` 重做 `,-1)]),_:1,__:[9]},8,[`disabled`])]),o[13]||=l(`div`,{class:`toolbar-section divider`},null,-1),l(`div`,ne,[d(S(n),{size:`small`,type:`error`,disabled:S(H),onClick:Q},{icon:C(()=>[d(e,{name:`mdi:delete-outline`,size:16,color:`currentColor`})]),default:C(()=>[o[10]||=u(` 清空 `,-1)]),_:1,__:[10]},8,[`disabled`])])])):s(`v-if`,!0),l(`div`,{class:p([`signature-canvas-wrapper`,{disabled:t.disabled,readonly:t.readonly}]),style:m({width:typeof t.width==`number`?`${t.width}px`:t.width,height:typeof t.height==`number`?`${t.height}px`:t.height,backgroundColor:t.backgroundColor||`transparent`})},[l(`canvas`,{ref_key:`canvasRef`,ref:F,class:p([`signature-canvas`,{disabled:t.disabled,readonly:t.readonly}])},null,2),S(H)&&!t.disabled&&!t.readonly?(_(),c(`div`,re,` 请在此处签名 `)):s(`v-if`,!0)],6)]))}}),[[`__scopeId`,`data-v-1c733bfe`]]);export{w as i,E as n,T as r,P as t};
1
+ import{t as e}from"./C_Icon2.js";import{t}from"./export-helper.js";import{computed as n,createCommentVNode as r,createElementBlock as i,createElementVNode as a,createTextVNode as o,createVNode as s,defineComponent as c,normalizeClass as l,normalizeStyle as u,onMounted as d,onUnmounted as f,openBlock as p,reactive as m,readonly as h,ref as g,toRef as _,unref as v,withCtx as y}from"vue";import{NButton as b,NButtonGroup as x,NColorPicker as S,NInputNumber as C}from"naive-ui";function w(e){let{canvasRef:t,penConfig:n,mode:r,disabled:i,onStrokeComplete:a,onDrawStart:o,onDrawing:s}=e,c=g(!1),l=g([]),u=null,d=()=>{let e=t.value;if(!e||(u=e.getContext(`2d`,{willReadFrequently:!0}),!u))return;let n=window.devicePixelRatio||1,r=e.getBoundingClientRect();e.width=r.width*n,e.height=r.height*n,e.style.width=`${r.width}px`,e.style.height=`${r.height}px`,u.scale(n,n),u.lineCap=`round`,u.lineJoin=`round`},f=e=>{let n=t.value;if(!n)return{x:0,y:0};let r=n.getBoundingClientRect(),i,a;if(`touches`in e&&e.touches.length>0)({clientX:i,clientY:a}=e.touches[0]);else if(`clientX`in e)({clientX:i,clientY:a}=e);else return{x:0,y:0};return{x:i-r.left,y:a-r.top,timestamp:Date.now()}},p=(e,t,n,r=!1)=>{u&&(u.save(),r?(u.globalCompositeOperation=`destination-out`,u.lineWidth=20):(u.globalCompositeOperation=`source-over`,u.strokeStyle=n.color,u.lineWidth=n.width,u.globalAlpha=n.opacity),u.beginPath(),u.moveTo(e.x,e.y),u.lineTo(t.x,t.y),u.stroke(),u.restore())},m=e=>{if(i.value)return;e.preventDefault(),c.value=!0,l.value=[];let t=f(e);l.value.push(t),o()},_=e=>{if(!c.value||i.value)return;e.preventDefault();let t=f(e),a=l.value[l.value.length-1];a&&p(a,t,n.value,r.value===`eraser`),l.value.push(t),s(t)},v=e=>{!c.value||i.value||(e.preventDefault(),c.value=!1,l.value.length>0&&(a({points:[...l.value],color:n.value.color,width:n.value.width,opacity:n.value.opacity,mode:r.value}),l.value=[]))};return{isDrawing:h(c),initCanvas:d,bindEvents:()=>{let e=t.value;e&&(e.addEventListener(`mousedown`,m),e.addEventListener(`mousemove`,_),e.addEventListener(`mouseup`,v),e.addEventListener(`mouseleave`,v),e.addEventListener(`touchstart`,m,{passive:!1}),e.addEventListener(`touchmove`,_,{passive:!1}),e.addEventListener(`touchend`,v),e.addEventListener(`touchcancel`,v))},unbindEvents:()=>{let e=t.value;e&&(e.removeEventListener(`mousedown`,m),e.removeEventListener(`mousemove`,_),e.removeEventListener(`mouseup`,v),e.removeEventListener(`mouseleave`,v),e.removeEventListener(`touchstart`,m),e.removeEventListener(`touchmove`,_),e.removeEventListener(`touchend`,v),e.removeEventListener(`touchcancel`,v))},redrawStrokes:e=>{if(!u||!t.value)return;let n=t.value;u.clearRect(0,0,n.width,n.height),e.forEach(e=>{for(let t=1;t<e.points.length;t++)p(e.points[t-1],e.points[t],{color:e.color,width:e.width,opacity:e.opacity},e.mode===`eraser`)})},clearCanvas:()=>{!u||!t.value||u.clearRect(0,0,t.value.width,t.value.height)}}}function T(e={}){let{maxHistory:t=50,onChange:r}=e,i=g([]),a=g([]),o=g(-1),s=n(()=>o.value>0),c=n(()=>o.value<a.value.length-1),l=e=>{i.value.push(e),u()},u=()=>{a.value=a.value.slice(0,o.value+1),a.value.push([...i.value]),o.value++,a.value.length>t&&(a.value.shift(),o.value--),r?.(i.value)},d=()=>s.value?(o.value--,i.value=[...a.value[o.value]],r?.(i.value),!0):!1,f=()=>c.value?(o.value++,i.value=[...a.value[o.value]],r?.(i.value),!0):!1,p=()=>{i.value=[],a.value=[[]],o.value=0,r?.(i.value)},m=e=>{i.value=[...e],a.value=[[...e]],o.value=0,r?.(i.value)},_=n(()=>i.value.length===0);return a.value=[[]],o.value=0,{strokes:h(i),canUndo:h(s),canRedo:h(c),isEmpty:h(_),addStroke:l,undo:d,redo:f,clear:p,loadData:m}}function E(e){let{canvasRef:t,watermark:n}=e,r=(e,t,n,r)=>{let i={"top-left":{x:10,y:n+10},"top-right":{x:e.width-t-10,y:n+10},"bottom-left":{x:10,y:e.height-10},"bottom-right":{x:e.width-t-10,y:e.height-10}};return i[r]||i[`bottom-right`]},i=(e,t)=>{let i=e.getContext(`2d`);if(!i||!n?.value?.show)return;let a={fontSize:n.value.fontSize||12,color:n.value.color||`#999999`,position:n.value.position||`bottom-right`};i.save(),i.font=`${a.fontSize}px Arial`,i.fillStyle=a.color,i.textBaseline=`bottom`;let o=i.measureText(t).width,{x:s,y:c}=r(e,o,a.fontSize,a.position);i.fillText(t,s,c),i.restore()},a=(e,t,n)=>{let r=document.createElement(`canvas`);r.width=e.width,r.height=e.height;let i=r.getContext(`2d`);if(!i)throw Error(`无法创建临时 Canvas`);return t&&(i.fillStyle=n,i.fillRect(0,0,r.width,r.height)),i.drawImage(e,0,0),{canvas:r,ctx:i}},o=(e,t)=>{let{includeBackground:r=!1,backgroundColor:o=`#FFFFFF`,includeWatermark:s=!1}=t,{canvas:c}=a(e,r,o);return s&&n?.value?.text&&i(c,n.value.text),c},s=(e,t)=>new Promise((n,r)=>{e.toBlob(e=>e?n(e):r(Error(`导出失败`)),`image/png`,t)}),c=e=>{let t=e.getContext(`2d`);if(!t)return!0;let{data:n}=t.getImageData(0,0,e.width,e.height);return!n.some(e=>e!==0)},l=async(e={})=>{let n=t.value;if(!n)throw Error(`Canvas 未初始化`);if(c(n))throw Error(`签名为空,请先签名后再导出`);let{format:r=`png`,quality:i=.92}=e;if(r===`svg`)return`data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg"><text>SVG export placeholder</text></svg>`;let a=o(n,e);if(r===`blob`)return s(a,i);let l=r===`jpeg`?`image/jpeg`:`image/png`;return a.toDataURL(l,i)};return{exportSignature:l,download:async(e=`signature`,t={})=>{let n=t.format||`png`,r=await l({...t,format:n});if(r instanceof Blob){let t=URL.createObjectURL(r),i=document.createElement(`a`);i.href=t,i.download=`${e}.${n}`,i.click(),URL.revokeObjectURL(t)}else if(typeof r==`string`){let t=document.createElement(`a`);t.href=r,t.download=`${e}.${n}`,t.click()}},loadImage:async e=>{let n=t.value;if(!n)throw Error(`Canvas 未初始化`);let r=n.getContext(`2d`);if(!r)throw Error(`无法获取 Canvas 上下文`);return new Promise((t,i)=>{let a=new Image;a.crossOrigin=`anonymous`,a.onload=()=>{r.clearRect(0,0,n.width,n.height),r.drawImage(a,0,0,n.width,n.height),t()},a.onerror=()=>i(Error(`图片加载失败: ${e}`)),a.src=e})}}}const D={color:`#000000`,width:2,opacity:1},O={show:!1,text:``,fontSize:12,color:`#999999`,position:`bottom-right`},k=[`#000000`,`#FF0000`,`#0000FF`,`#00AA00`,`#FF6600`,`#9900FF`],A={class:`c-signature`},j={key:0,class:`signature-toolbar`},M={class:`toolbar-section`},ee={key:0,class:`toolbar-section`},te={key:1,class:`toolbar-section`},ne={class:`toolbar-section`},re={class:`toolbar-section`},N={key:0,class:`canvas-placeholder`};var P=t(c({name:`C_Signature`,__name:`index`,props:{width:{default:`100%`},height:{default:300},penConfig:{},eraserConfig:{},disabled:{type:Boolean,default:!1},readonly:{type:Boolean,default:!1},backgroundImage:{},backgroundColor:{},watermark:{},showToolbar:{type:Boolean,default:!0},maxHistory:{default:50}},emits:[`start-draw`,`drawing`,`end-draw`,`clear`,`undo`,`redo`,`change`],setup(t,{expose:n,emit:c}){let h=t,P=c,F=g(null),I=g(`pen`),L=m({...D,...h.penConfig}),R=m({...O,...h.watermark}),{strokes:z,canUndo:B,canRedo:V,isEmpty:H,addStroke:U,undo:W,redo:G,clear:K,loadData:q}=T({maxHistory:h.maxHistory,onChange:e=>{J.redrawStrokes(e),P(`change`,e)}}),J=w({canvasRef:F,penConfig:_(L),mode:I,disabled:_(h,`disabled`),onStrokeComplete:e=>{U(e),P(`end-draw`,e)},onDrawStart:()=>P(`start-draw`),onDrawing:e=>P(`drawing`,e)}),Y=E({canvasRef:F,watermark:_(R)}),X=()=>{let e=W();return e&&P(`undo`),e},Z=()=>{let e=G();return e&&P(`redo`),e},Q=()=>{K(),J.clearCanvas(),P(`clear`)},ie=async e=>Y.exportSignature(e),ae=async(e,t)=>Y.download(e,t),$=async e=>{await Y.loadImage(e),K()};return d(()=>{J.initCanvas(),J.bindEvents(),h.backgroundImage&&$(h.backgroundImage)}),f(()=>J.unbindEvents()),n({clear:Q,undo:X,redo:Z,export:ie,download:ae,loadImage:$,getSignatureData:()=>z.value,loadSignatureData:e=>q(e),isEmpty:()=>H.value}),(t,n)=>(p(),i(`div`,A,[t.showToolbar?(p(),i(`div`,j,[a(`div`,M,[s(v(x),null,{default:y(()=>[s(v(b),{type:I.value===`pen`?`primary`:`default`,size:`small`,onClick:n[0]||=e=>I.value=`pen`},{icon:y(()=>[s(e,{name:`mdi:draw`,size:16,color:`currentColor`})]),default:y(()=>[n[4]||=o(` 画笔 `,-1)]),_:1,__:[4]},8,[`type`]),s(v(b),{type:I.value===`eraser`?`primary`:`default`,size:`small`,onClick:n[1]||=e=>I.value=`eraser`},{icon:y(()=>[s(e,{name:`mdi:eraser`,size:16,color:`currentColor`})]),default:y(()=>[n[5]||=o(` 橡皮擦 `,-1)]),_:1,__:[5]},8,[`type`])]),_:1})]),n[11]||=a(`div`,{class:`toolbar-section divider`},null,-1),I.value===`pen`?(p(),i(`div`,ee,[n[6]||=a(`span`,{class:`section-label`},`颜色`,-1),s(v(S),{value:L.color,"onUpdate:value":n[2]||=e=>L.color=e,"show-alpha":!1,size:`small`,swatches:v(k)},null,8,[`value`,`swatches`])])):r(`v-if`,!0),I.value===`pen`?(p(),i(`div`,te,[n[7]||=a(`span`,{class:`section-label`},`粗细`,-1),s(v(C),{value:L.width,"onUpdate:value":n[3]||=e=>L.width=e,min:1,max:20,size:`small`,style:{width:`80px`}},null,8,[`value`])])):r(`v-if`,!0),n[12]||=a(`div`,{class:`toolbar-section divider`},null,-1),a(`div`,ne,[s(v(b),{size:`small`,disabled:!v(B),onClick:X},{icon:y(()=>[s(e,{name:`mdi:undo`,size:16,color:`currentColor`})]),default:y(()=>[n[8]||=o(` 撤销 `,-1)]),_:1,__:[8]},8,[`disabled`]),s(v(b),{size:`small`,disabled:!v(V),onClick:Z},{icon:y(()=>[s(e,{name:`mdi:redo`,size:16,color:`currentColor`})]),default:y(()=>[n[9]||=o(` 重做 `,-1)]),_:1,__:[9]},8,[`disabled`])]),n[13]||=a(`div`,{class:`toolbar-section divider`},null,-1),a(`div`,re,[s(v(b),{size:`small`,type:`error`,disabled:v(H),onClick:Q},{icon:y(()=>[s(e,{name:`mdi:delete-outline`,size:16,color:`currentColor`})]),default:y(()=>[n[10]||=o(` 清空 `,-1)]),_:1,__:[10]},8,[`disabled`])])])):r(`v-if`,!0),a(`div`,{class:l([`signature-canvas-wrapper`,{disabled:t.disabled,readonly:t.readonly}]),style:u({width:typeof t.width==`number`?`${t.width}px`:t.width,height:typeof t.height==`number`?`${t.height}px`:t.height,backgroundColor:t.backgroundColor||`transparent`})},[a(`canvas`,{ref_key:`canvasRef`,ref:F,class:l([`signature-canvas`,{disabled:t.disabled,readonly:t.readonly}])},null,2),v(H)&&!t.disabled&&!t.readonly?(p(),i(`div`,N,` 请在此处签名 `)):r(`v-if`,!0)],6)]))}}),[[`__scopeId`,`data-v-fbc647a9`]]);export{w as i,E as n,T as r,P as t};
2
2
  //# sourceMappingURL=C_Signature2.js.map